mirror of
https://github.com/openmc-dev/openmc.git
synced 2026-07-21 14:35:27 -04:00
Merge branch 'develop' into photon-alund
This commit is contained in:
commit
460452d4f7
746 changed files with 17707 additions and 10855 deletions
9
.gitignore
vendored
9
.gitignore
vendored
|
|
@ -42,11 +42,8 @@ results_error.dat
|
|||
inputs_error.dat
|
||||
results_test.dat
|
||||
|
||||
# Test build files
|
||||
tests/build/
|
||||
tests/coverage/
|
||||
tests/memcheck/
|
||||
tests/ctestscript.run
|
||||
# Test
|
||||
.pytest_cache/
|
||||
|
||||
# HDF5 files
|
||||
*.h5
|
||||
|
|
@ -99,3 +96,5 @@ examples/jupyter/plots
|
|||
.cache/
|
||||
.tox/
|
||||
.python-version
|
||||
.coverage
|
||||
htmlcov
|
||||
74
.travis.yml
74
.travis.yml
|
|
@ -2,66 +2,44 @@ sudo: required
|
|||
dist: trusty
|
||||
language: python
|
||||
python:
|
||||
- "2.7"
|
||||
- "3.4"
|
||||
- "3.5"
|
||||
- "3.6"
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- gfortran
|
||||
- g++
|
||||
- mpich
|
||||
- libmpich-dev
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/nndc_hdf5
|
||||
- $HOME/endf-b-vii.1
|
||||
env:
|
||||
- OPENMC_CONFIG="check_source"
|
||||
- OPENMC_CONFIG="^hdf5-debug$"
|
||||
- OPENMC_CONFIG="^omp-hdf5-debug$"
|
||||
- OPENMC_CONFIG="^mpi-hdf5-debug$"
|
||||
- OPENMC_CONFIG="^phdf5-debug$"
|
||||
|
||||
# We aren't testing the check_source script so just run it with Python 3.
|
||||
matrix:
|
||||
exclude:
|
||||
- python: "2.7"
|
||||
env: OPENMC_CONFIG="check_source"
|
||||
|
||||
global:
|
||||
- FC=gfortran
|
||||
- MPI_DIR=/usr
|
||||
- HDF5_ROOT=/usr
|
||||
- OMP_NUM_THREADS=2
|
||||
- OPENMC_CROSS_SECTIONS=$HOME/nndc_hdf5/cross_sections.xml
|
||||
- OPENMC_ENDF_DATA=$HOME/endf-b-vii.1
|
||||
- OPENMC_MULTIPOLE_LIBRARY=$HOME/multipole_lib
|
||||
- PATH=$PATH:$HOME/NJOY2016/build
|
||||
- DISPLAY=:99.0
|
||||
matrix:
|
||||
- OMP=n MPI=n PHDF5=n
|
||||
- OMP=y MPI=n PHDF5=n
|
||||
- OMP=n MPI=y PHDF5=n
|
||||
- OMP=n MPI=y PHDF5=y
|
||||
before_install:
|
||||
- if [[ $OPENMC_CONFIG != "check_source" ]]; then
|
||||
sudo add-apt-repository ppa:nschloe/hdf5-backports -y;
|
||||
sudo apt-get update -q;
|
||||
sudo apt-get install libhdf5-serial-dev libhdf5-mpich-dev -y;
|
||||
export FC=gfortran;
|
||||
export MPI_DIR=/usr;
|
||||
export PHDF5_DIR=/usr;
|
||||
export HDF5_DIR=/usr;
|
||||
fi
|
||||
|
||||
- sudo add-apt-repository ppa:nschloe/hdf5-backports -y
|
||||
- sudo apt-get update -q
|
||||
- sudo apt-get install libhdf5-serial-dev libhdf5-mpich-dev -y
|
||||
install:
|
||||
- if [[ $OPENMC_CONFIG != "check_source" ]]; then
|
||||
pip install numpy cython;
|
||||
pip install -e .[test];
|
||||
fi
|
||||
|
||||
- ./tools/ci/travis-install.sh
|
||||
before_script:
|
||||
- if [[ $OPENMC_CONFIG != "check_source" ]]; then
|
||||
if [[ ! -e $HOME/nndc_hdf5/cross_sections.xml ]]; then
|
||||
wget https://anl.box.com/shared/static/a6sw2cep34wlz6b9i9jwiotaqoayxcxt.xz -O - | tar -C $HOME -xvJ;
|
||||
fi;
|
||||
export OPENMC_CROSS_SECTIONS=$HOME/nndc_hdf5/cross_sections.xml;
|
||||
git clone --branch=master git://github.com/smharper/windowed_multipole_library.git wmp_lib;
|
||||
tar xzvf wmp_lib/multipole_lib.tar.gz;
|
||||
export OPENMC_MULTIPOLE_LIBRARY=$PWD/multipole_lib;
|
||||
fi
|
||||
|
||||
- ./tools/ci/travis-before-script.sh
|
||||
script:
|
||||
- cd tests
|
||||
- export OMP_NUM_THREADS=2
|
||||
- if [[ $OPENMC_CONFIG == "check_source" ]]; then
|
||||
./check_source.py;
|
||||
else
|
||||
./run_tests.py -C $OPENMC_CONFIG -j 2 &&
|
||||
pytest --cov=../openmc unit_tests/;
|
||||
fi
|
||||
- cd ..
|
||||
- ./tools/ci/travis-script.sh
|
||||
after_success:
|
||||
- coveralls
|
||||
|
|
|
|||
165
CMakeLists.txt
165
CMakeLists.txt
|
|
@ -1,4 +1,4 @@
|
|||
cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR)
|
||||
cmake_minimum_required(VERSION 3.0 FATAL_ERROR)
|
||||
project(openmc Fortran C CXX)
|
||||
|
||||
# Setup output directories
|
||||
|
|
@ -21,11 +21,6 @@ if (${UNIX})
|
|||
add_definitions(-DUNIX)
|
||||
endif()
|
||||
|
||||
# Set MACOSX_RPATH
|
||||
if(POLICY CMP0042)
|
||||
cmake_policy(SET CMP0042 NEW)
|
||||
endif()
|
||||
|
||||
#===============================================================================
|
||||
# Command line options
|
||||
#===============================================================================
|
||||
|
|
@ -46,16 +41,19 @@ add_definitions(-DMAX_COORD=${maxcoord})
|
|||
#===============================================================================
|
||||
|
||||
set(MPI_ENABLED FALSE)
|
||||
if($ENV{FC} MATCHES "mpi[^/]*$")
|
||||
if($ENV{FC} MATCHES "(mpi[^/]*|ftn)$")
|
||||
message("-- Detected MPI wrapper: $ENV{FC}")
|
||||
add_definitions(-DMPI)
|
||||
add_definitions(-DOPENMC_MPI)
|
||||
set(MPI_ENABLED TRUE)
|
||||
|
||||
# Get directory containing MPI wrapper
|
||||
get_filename_component(MPI_DIR $ENV{FC} DIRECTORY)
|
||||
endif()
|
||||
|
||||
# Check for Fortran 2008 MPI interface
|
||||
if(MPI_ENABLED AND mpif08)
|
||||
message("-- Using Fortran 2008 MPI bindings")
|
||||
add_definitions(-DMPIF08)
|
||||
add_definitions(-DOPENMC_MPIF08)
|
||||
endif()
|
||||
|
||||
#===============================================================================
|
||||
|
|
@ -116,9 +114,9 @@ if(CMAKE_Fortran_COMPILER_ID STREQUAL GNU)
|
|||
endif()
|
||||
|
||||
# GCC compiler options
|
||||
list(APPEND f90flags -cpp -std=f2008ts -fbacktrace -O2)
|
||||
list(APPEND f90flags -cpp -std=f2008ts -fbacktrace -O2 -fstack-arrays)
|
||||
if(debug)
|
||||
list(REMOVE_ITEM f90flags -O2)
|
||||
list(REMOVE_ITEM f90flags -O2 -fstack-arrays)
|
||||
list(APPEND f90flags -g -Wall -Wno-unused-dummy-argument -pedantic
|
||||
-fbounds-check -ffpe-trap=invalid,overflow,underflow)
|
||||
list(APPEND ldflags -g)
|
||||
|
|
@ -251,9 +249,26 @@ elseif(CMAKE_C_COMPILER_ID MATCHES Clang)
|
|||
|
||||
endif()
|
||||
|
||||
list(APPEND cxxflags -std=c++11 -O2)
|
||||
if(debug)
|
||||
list(REMOVE_ITEM cxxflags -O2)
|
||||
list(APPEND cxxflags -g -O0)
|
||||
endif()
|
||||
if(profile)
|
||||
list(APPEND cxxflags -pg)
|
||||
endif()
|
||||
if(optimize)
|
||||
list(REMOVE_ITEM cxxflags -O2)
|
||||
list(APPEND cxxflags -O3)
|
||||
endif()
|
||||
if(openmp)
|
||||
list(APPEND cxxflags -fopenmp)
|
||||
endif()
|
||||
|
||||
# Show flags being used
|
||||
message(STATUS "Fortran flags: ${f90flags}")
|
||||
message(STATUS "C flags: ${cflags}")
|
||||
message(STATUS "C++ flags: ${cxxflags}")
|
||||
message(STATUS "Linker flags: ${ldflags}")
|
||||
|
||||
#===============================================================================
|
||||
|
|
@ -281,10 +296,30 @@ target_link_libraries(pugixml_fortran pugixml)
|
|||
# RPATH information
|
||||
#===============================================================================
|
||||
|
||||
# This block of code ensures that dynamic libraries can be found via the RPATH
|
||||
# whether the executable is the original one from the build directory or the
|
||||
# installed one in CMAKE_INSTALL_PREFIX. Ref:
|
||||
# https://cmake.org/Wiki/CMake_RPATH_handling#Always_full_RPATH
|
||||
|
||||
# use, i.e. don't skip the full RPATH for the build tree
|
||||
set(CMAKE_SKIP_BUILD_RPATH FALSE)
|
||||
|
||||
# when building, don't use the install RPATH already
|
||||
# (but later on when installing)
|
||||
set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
|
||||
|
||||
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
|
||||
|
||||
# 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)
|
||||
|
||||
# the RPATH to be used when installing, but only if it's not a system directory
|
||||
list(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_PREFIX}/lib" isSystemDir)
|
||||
if("${isSystemDir}" STREQUAL "-1")
|
||||
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
|
||||
endif()
|
||||
|
||||
#===============================================================================
|
||||
# Build faddeeva library
|
||||
#===============================================================================
|
||||
|
|
@ -292,7 +327,7 @@ set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
|
|||
add_library(faddeeva STATIC src/faddeeva/Faddeeva.c)
|
||||
|
||||
#===============================================================================
|
||||
# Build OpenMC executable
|
||||
# List source files. Define the libopenmc and the OpenMC executable
|
||||
#===============================================================================
|
||||
|
||||
set(program "openmc")
|
||||
|
|
@ -310,7 +345,6 @@ set(LIBOPENMC_FORTRAN_SRC
|
|||
src/cmfd_prod_operator.F90
|
||||
src/cmfd_solver.F90
|
||||
src/constants.F90
|
||||
src/cross_section.F90
|
||||
src/dict_header.F90
|
||||
src/distribution_multivariate.F90
|
||||
src/distribution_univariate.F90
|
||||
|
|
@ -340,7 +374,6 @@ set(LIBOPENMC_FORTRAN_SRC
|
|||
src/output.F90
|
||||
src/particle_header.F90
|
||||
src/particle_restart.F90
|
||||
src/particle_restart_write.F90
|
||||
src/photon_header.F90
|
||||
src/photon_physics.F90
|
||||
src/physics_common.F90
|
||||
|
|
@ -401,19 +434,44 @@ set(LIBOPENMC_FORTRAN_SRC
|
|||
src/tallies/trigger.F90
|
||||
src/tallies/trigger_header.F90
|
||||
)
|
||||
add_library(libopenmc SHARED ${LIBOPENMC_FORTRAN_SRC})
|
||||
set(LIBOPENMC_CXX_SRC
|
||||
src/error.h
|
||||
src/hdf5_interface.h
|
||||
src/random_lcg.cpp
|
||||
src/random_lcg.h
|
||||
src/surface.cpp
|
||||
src/surface.h
|
||||
src/xml_interface.h
|
||||
src/pugixml/pugixml.cpp
|
||||
src/pugixml/pugixml.hpp)
|
||||
add_library(libopenmc SHARED ${LIBOPENMC_FORTRAN_SRC} ${LIBOPENMC_CXX_SRC})
|
||||
set_target_properties(libopenmc PROPERTIES OUTPUT_NAME openmc)
|
||||
add_executable(${program} src/main.F90)
|
||||
|
||||
#===============================================================================
|
||||
# Add compiler/linker flags
|
||||
#===============================================================================
|
||||
|
||||
set_property(TARGET ${program} libopenmc pugixml_fortran
|
||||
PROPERTY LINKER_LANGUAGE Fortran)
|
||||
|
||||
target_include_directories(libopenmc PUBLIC ${HDF5_INCLUDE_DIRS})
|
||||
|
||||
# set compile flags via target_compile_options
|
||||
# The executable and the faddeeva package use only one language. They can be
|
||||
# set via target_compile_options which accepts a list.
|
||||
target_compile_options(${program} PUBLIC ${f90flags})
|
||||
target_compile_options(libopenmc PUBLIC ${f90flags})
|
||||
target_compile_options(faddeeva PRIVATE ${cflags})
|
||||
|
||||
# The libopenmc library has both F90 and C++ so the compile flags must be set
|
||||
# file-by-file via set_source_file_properties. The compile flags must first be
|
||||
# converted from lists to strings.
|
||||
string(REPLACE ";" " " f90flags "${f90flags}")
|
||||
string(REPLACE ";" " " cxxflags "${cxxflags}")
|
||||
set_source_files_properties(${LIBOPENMC_FORTRAN_SRC} PROPERTIES COMPILE_FLAGS
|
||||
${f90flags})
|
||||
set_source_files_properties(${LIBOPENMC_CXX_SRC} PROPERTIES COMPILE_FLAGS
|
||||
${cxxflags})
|
||||
|
||||
# Add HDF5 library directories to link line with -L
|
||||
foreach(LIBDIR ${HDF5_LIBRARY_DIRS})
|
||||
list(APPEND ldflags "-L${LIBDIR}")
|
||||
|
|
@ -421,7 +479,8 @@ 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(libopenmc ${ldflags} ${HDF5_LIBRARIES} pugixml_fortran faddeeva)
|
||||
target_link_libraries(libopenmc ${ldflags} ${HDF5_LIBRARIES} pugixml_fortran
|
||||
faddeeva)
|
||||
target_link_libraries(${program} ${ldflags} libopenmc)
|
||||
|
||||
#===============================================================================
|
||||
|
|
@ -438,72 +497,10 @@ add_custom_command(TARGET libopenmc POST_BUILD
|
|||
# Install executable, scripts, manpage, license
|
||||
#===============================================================================
|
||||
|
||||
install(TARGETS ${program} RUNTIME DESTINATION bin)
|
||||
install(TARGETS ${program} libopenmc
|
||||
RUNTIME DESTINATION bin
|
||||
LIBRARY DESTINATION lib
|
||||
ARCHIVE DESTINATION lib)
|
||||
install(DIRECTORY src/relaxng DESTINATION share/openmc)
|
||||
install(FILES man/man1/openmc.1 DESTINATION share/man/man1)
|
||||
install(FILES LICENSE DESTINATION "share/doc/${program}" RENAME copyright)
|
||||
|
||||
find_package(PythonInterp)
|
||||
if(PYTHONINTERP_FOUND)
|
||||
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 "set(ENV{PYTHONPATH} \"${CMAKE_INSTALL_PREFIX}/lib/python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}/site-packages\")")
|
||||
install(CODE "execute_process(
|
||||
COMMAND ${PYTHON_EXECUTABLE} setup.py install
|
||||
--prefix=${CMAKE_INSTALL_PREFIX}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
#===============================================================================
|
||||
# Regression tests
|
||||
#===============================================================================
|
||||
|
||||
# This allows for dashboard configuration
|
||||
include(CTest)
|
||||
|
||||
# Get a list of all the tests to run
|
||||
file(GLOB_RECURSE TESTS ${CMAKE_CURRENT_SOURCE_DIR}/tests/test_*.py)
|
||||
|
||||
# Loop through all the tests
|
||||
foreach(test ${TESTS})
|
||||
# Remove unit tests
|
||||
if(test MATCHES ".*unit_tests.*")
|
||||
continue()
|
||||
endif()
|
||||
|
||||
# Get test information
|
||||
get_filename_component(TEST_NAME ${test} NAME)
|
||||
get_filename_component(TEST_PATH ${test} PATH)
|
||||
|
||||
if (DEFINED ENV{MEM_CHECK})
|
||||
# Generate input files if needed
|
||||
if (NOT EXISTS "${TEST_PATH}/geometry.xml")
|
||||
execute_process(COMMAND ${PYTHON_EXECUTABLE} ${TEST_NAME} --build-inputs
|
||||
WORKING_DIRECTORY ${TEST_PATH})
|
||||
endif()
|
||||
|
||||
# Add serial test
|
||||
add_test(NAME ${TEST_NAME}
|
||||
WORKING_DIRECTORY ${TEST_PATH}
|
||||
COMMAND $<TARGET_FILE:openmc>)
|
||||
else()
|
||||
# Check serial/parallel
|
||||
if (${MPI_ENABLED})
|
||||
# Preform a parallel test
|
||||
add_test(NAME ${TEST_NAME}
|
||||
WORKING_DIRECTORY ${TEST_PATH}
|
||||
COMMAND ${PYTHON_EXECUTABLE} ${TEST_NAME} --exe $<TARGET_FILE:openmc>
|
||||
--mpi_exec $ENV{MPI_DIR}/bin/mpiexec)
|
||||
else()
|
||||
# Perform a serial test
|
||||
add_test(NAME ${TEST_NAME}
|
||||
WORKING_DIRECTORY ${TEST_PATH}
|
||||
COMMAND ${PYTHON_EXECUTABLE} ${TEST_NAME} --exe $<TARGET_FILE:openmc>)
|
||||
endif()
|
||||
endif()
|
||||
endforeach(test)
|
||||
|
|
|
|||
2
LICENSE
2
LICENSE
|
|
@ -1,4 +1,4 @@
|
|||
Copyright (c) 2011-2017 Massachusetts Institute of Technology
|
||||
Copyright (c) 2011-2018 Massachusetts Institute of Technology
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
|
|
|
|||
|
|
@ -13,10 +13,6 @@ PAPEROPT_a4 = -D latex_paper_size=a4
|
|||
PAPEROPT_letter = -D latex_paper_size=letter
|
||||
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
|
||||
|
||||
# SVG to PDF conversion
|
||||
SVG2PDF = inkscape
|
||||
PDFS = $(patsubst %.svg,%.pdf,$(wildcard $(IMAGEDIR)/*.svg))
|
||||
|
||||
# Tikz to PNG conversion
|
||||
PNGS = $(patsubst %.tex,%.png,$(wildcard $(IMAGEDIR)/*.tex))
|
||||
|
||||
|
|
@ -41,21 +37,13 @@ help:
|
|||
@echo " linkcheck to check all external links for integrity"
|
||||
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
|
||||
|
||||
# Pattern rule for converting SVG to PDF
|
||||
%.pdf: %.svg
|
||||
$(SVG2PDF) -f $< -A $@
|
||||
|
||||
%.png: %.tex
|
||||
pdflatex --interaction=nonstopmode --output-directory=$(IMAGEDIR) $<
|
||||
pdftoppm -r 120 -singlefile $(patsubst %.tex,%.pdf, $<) $(basename $<)
|
||||
convert -trim -fuzz 2% -transparent white $(patsubst %.tex,%.ppm,$<) $@
|
||||
|
||||
# Rule to build PDFs
|
||||
images: $(PDFS) $(PNGS)
|
||||
|
||||
clean:
|
||||
-rm -rf $(BUILDDIR)/*
|
||||
-rm -rf $(PDFS)
|
||||
-rm -rf source/pythonapi/generated/
|
||||
|
||||
html:
|
||||
|
|
|
|||
|
|
@ -4,32 +4,191 @@
|
|||
C API
|
||||
=====
|
||||
|
||||
The libopenmc shared library that is built when installing OpenMC exports a
|
||||
number of C interoperable functions and global variables that can be used for
|
||||
in-memory coupling. While it is possible to directly use the C API as documented
|
||||
here for coupling, most advanced users will find it easier to work with the
|
||||
Python bindings in the :py:mod:`openmc.capi` module.
|
||||
|
||||
.. warning:: The C API is still experimental and may undergo substantial changes
|
||||
in future releases.
|
||||
|
||||
----------------
|
||||
Type Definitions
|
||||
----------------
|
||||
|
||||
.. c:type:: Bank
|
||||
|
||||
Attributes of a source particle.
|
||||
|
||||
.. c:member:: double wgt
|
||||
|
||||
Weight of the particle
|
||||
|
||||
.. c:member:: double xyz[3]
|
||||
|
||||
Position of the particle (units of cm)
|
||||
|
||||
.. c:member:: double uvw[3]
|
||||
|
||||
Unit vector indicating direction of the particle
|
||||
|
||||
.. c:member:: double E
|
||||
|
||||
Energy of the particle in eV
|
||||
|
||||
.. c:member:: int delayed_group
|
||||
|
||||
If the particle is a delayed neutron, indicates which delayed precursor
|
||||
group it was born from. If not a delayed neutron, this member is zero.
|
||||
|
||||
---------
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. c:function:: void openmc_calculate_volumes()
|
||||
|
||||
Run a stochastic volume calculation
|
||||
|
||||
.. c:function:: int openmc_cell_get_fill(int32_t index, int* type, int32_t** indices, int32_t* n)
|
||||
|
||||
Get the fill for a cell
|
||||
|
||||
:param int32_t index: Index in the cells array
|
||||
:param int* type: Type of the fill
|
||||
:param int32_t** indices: Array of material indices for cell
|
||||
:param int32_t* n: Length of indices array
|
||||
:return: Return status (negative if an error occurred)
|
||||
:rtype: int
|
||||
|
||||
.. c:function:: int openmc_cell_get_id(int32_t index, int32_t* id)
|
||||
|
||||
Get the ID of a cell
|
||||
|
||||
:param index: Index in the cells array
|
||||
:type index: int32_t
|
||||
:param id: ID of the cell
|
||||
:type id: int32_t*
|
||||
:param int32_t index: Index in the cells array
|
||||
:param int32_t* id: ID of the cell
|
||||
:return: Return status (negative if an error occurred)
|
||||
:rtype: int
|
||||
|
||||
.. c:function:: int openmc_cell_set_temperature(index index, double T, int32_t* instance)
|
||||
.. c:function:: int openmc_cell_set_fill(int32_t index, int type, int32_t n, const int32_t* indices)
|
||||
|
||||
Set the fill for a cell
|
||||
|
||||
:param int32_t index: Index in the cells array
|
||||
:param int type: Type of the fill
|
||||
:param int32_t n: Length of indices array
|
||||
:param indices: Array of material indices for cell
|
||||
:type indices: const int32_t*
|
||||
:return: Return status (negative if an error occurred)
|
||||
:rtype: int
|
||||
|
||||
.. c:function:: int openmc_cell_set_id(int32_t index, int32_t id)
|
||||
|
||||
Set the ID of a cell
|
||||
|
||||
:param int32_t index: Index in the cells array
|
||||
:param int32_t id: ID of the cell
|
||||
:return: Return status (negative if an error occurred)
|
||||
:rtype: int
|
||||
|
||||
.. c:function:: int openmc_cell_set_temperature(index index, double T, const int32_t* instance)
|
||||
|
||||
Set the temperature of a cell.
|
||||
|
||||
:param index: Index in the cells array
|
||||
:type index: int32_t
|
||||
:param T: Temperature in Kelvin
|
||||
:type T: double
|
||||
:param int32_t index: Index in the cells array
|
||||
:param double T: Temperature in Kelvin
|
||||
:param instance: Which instance of the cell. To set the temperature for all
|
||||
instances, pass a null pointer.
|
||||
:type instance: int32_t*
|
||||
:type instance: const int32_t*
|
||||
:return: Return status (negative if an error occurred)
|
||||
:rtype: int
|
||||
|
||||
.. c:function:: int openmc_energy_filter_get_bins(int32_t index, double** energies, int32_t* n)
|
||||
|
||||
Return the bounding energies for an energy filter
|
||||
|
||||
:param int32_t index: Index in the filters array
|
||||
:param double** energies: Bounding energies of the bins for the energy filter
|
||||
:param int32_t* n: Number of energies specified
|
||||
:return: Return status (negative if an error occurred)
|
||||
:rtype: int
|
||||
|
||||
.. c:function:: int openmc_energy_filter_set_bins(int32_t index, int32_t n, const double* energies)
|
||||
|
||||
Set the bounding energies for an energy filter
|
||||
|
||||
:param int32_t index: Index in the filters array
|
||||
:param int32_t n: Number of energies specified
|
||||
:param energies: Bounding energies of the bins for the energy filter
|
||||
:type energies: const double*
|
||||
:return: Return status (negative if an error occurred)
|
||||
:rtype: int
|
||||
|
||||
.. c:function:: int openmc_extend_cells(int32_t n, int32_t* index_start, int32_t* index_end)
|
||||
|
||||
Extend the cells array by n elements
|
||||
|
||||
:param int32_t n: Number of cells to create
|
||||
:param int32_t* index_start: Index of first new cell
|
||||
:param int32_t* index_end: Index of last new cell
|
||||
:return: Return status (negative if an error occurred)
|
||||
:rtype: int
|
||||
|
||||
.. c:function:: int openmc_extend_filters(int32_t n, int32_t* index_start, int32_t* index_end)
|
||||
|
||||
Extend the filters array by n elements
|
||||
|
||||
:param int32_t n: Number of filters to create
|
||||
:param int32_t* index_start: Index of first new filter
|
||||
:param int32_t* index_end: Index of last new filter
|
||||
:return: Return status (negative if an error occurred)
|
||||
:rtype: int
|
||||
|
||||
.. c:function:: int openmc_extend_materials(int32_t n, int32_t* index_start, int32_t* index_end)
|
||||
|
||||
Extend the materials array by n elements
|
||||
|
||||
:param int32_t n: Number of materials to create
|
||||
:param int32_t* index_start: Index of first new material
|
||||
:param int32_t* index_end: Index of last new material
|
||||
:return: Return status (negative if an error occurred)
|
||||
:rtype: int
|
||||
|
||||
.. c:function:: int openmc_extend_sources(int32_t n, int32_t* index_start, int32_t* index_end)
|
||||
|
||||
Extend the external sources array by n elements
|
||||
|
||||
:param int32_t n: Number of sources to create
|
||||
:param int32_t* index_start: Index of first new source
|
||||
:param int32_t* index_end: Index of last new source
|
||||
:return: Return status (negative if an error occurred)
|
||||
:rtype: int
|
||||
|
||||
.. c:function:: int openmc_extend_tallies(int32_t n, int32_t* index_start, int32_t* index_end)
|
||||
|
||||
Extend the tallies array by n elements
|
||||
|
||||
:param int32_t n: Number of tallies to create
|
||||
:param int32_t* index_start: Index of first new tally
|
||||
:param int32_t* index_end: Index of last new tally
|
||||
:return: Return status (negative if an error occurred)
|
||||
:rtype: int
|
||||
|
||||
.. c:function:: int openmc_filter_get_id(int32_t index, int32_t* id)
|
||||
|
||||
Get the ID of a filter
|
||||
|
||||
:param int32_t index: Index in the filters array
|
||||
:param int32_t* id: ID of the filter
|
||||
:return: Return status (negative if an error occurred)
|
||||
:rtype: int
|
||||
|
||||
.. c:function:: int openmc_filter_set_id(int32_t index, int32_t id)
|
||||
|
||||
Set the ID of a filter
|
||||
|
||||
:param int32_t index: Index in the filters array
|
||||
:param int32_t id: ID of the filter
|
||||
:return: Return status (negative if an error occurred)
|
||||
:rtype: int
|
||||
|
||||
|
|
@ -41,54 +200,41 @@ C API
|
|||
|
||||
Determine the ID of the cell/material containing a given point
|
||||
|
||||
:param xyz: Cartesian coordinates
|
||||
:type xyz: double[3]
|
||||
:param rtype: Which ID to return (1=cell, 2=material)
|
||||
:type rtype: int
|
||||
:param id: ID of the cell/material found. If a material is requested and the
|
||||
point is in a void, the ID is 0. If an error occurs, the ID is -1.
|
||||
:type id: int32_t*
|
||||
:param instance: If a cell is repetaed in the geometry, the instance of the
|
||||
cell that was found and zero otherwise.
|
||||
:type instance: int32_t*
|
||||
:param double[3] xyz: Cartesian coordinates
|
||||
:param int rtype: Which ID to return (1=cell, 2=material)
|
||||
:param int32_t* id: ID of the cell/material found. If a material is requested
|
||||
and the point is in a void, the ID is 0. If an error
|
||||
occurs, the ID is -1.
|
||||
:param int32_t* instance: If a cell is repeated in the geometry, the instance
|
||||
of the cell that was found and zero otherwise.
|
||||
|
||||
.. c:function:: int openmc_get_cell_index(int32_t id, int32_t* index)
|
||||
|
||||
Get the index in the cells array for a cell with a given ID
|
||||
|
||||
:param id: ID of the cell
|
||||
:type id: int32_t
|
||||
:param index: Index in the cells array
|
||||
:type index: int32_t*
|
||||
:param int32_t id: ID of the cell
|
||||
:param int32_t* index: Index in the cells array
|
||||
:return: Return status (negative if an error occurs)
|
||||
:rtype: int
|
||||
|
||||
.. c:function:: int openmc_get_keff(double k_combined[])
|
||||
.. c:function:: int openmc_get_filter_index(int32_t id, int32_t* index)
|
||||
|
||||
:param k_combined: Combined estimate of k-effective
|
||||
:type k_combined: double[2]
|
||||
Get the index in the filters array for a filter with a given ID
|
||||
|
||||
:param int32_t id: ID of the filter
|
||||
:param int32_t* index: Index in the filters array
|
||||
:return: Return status (negative if an error occurs)
|
||||
:rtype: int
|
||||
|
||||
.. c:function:: int openmc_get_nuclide_index(char name[], int* index)
|
||||
.. c:function:: void openmc_get_filter_next_id(int32_t* id)
|
||||
|
||||
Get the index in the nuclides array for a nuclide with a given name
|
||||
Get an integer ID that has not been used by any filters.
|
||||
|
||||
:param name: Name of the nuclide
|
||||
:type name: char[]
|
||||
:param index: Index in the nuclides array
|
||||
:type index: int*
|
||||
:return: Return status (negative if an error occurs)
|
||||
:rtype: int
|
||||
:param int32_t* id: Unused integer ID
|
||||
|
||||
.. c:function:: int openmc_get_tally_index(int32_t id, int32_t* index)
|
||||
.. c:function:: int openmc_get_keff(double k_combined[2])
|
||||
|
||||
Get the index in the tallies array for a tally with a given ID
|
||||
|
||||
:param id: ID of the tally
|
||||
:type id: int32_t
|
||||
:param index: Index in the tallies array
|
||||
:type index: int32_t*
|
||||
:param double[2] k_combined: Combined estimate of k-effective
|
||||
:return: Return status (negative if an error occurs)
|
||||
:rtype: int
|
||||
|
||||
|
|
@ -96,10 +242,26 @@ C API
|
|||
|
||||
Get the index in the materials array for a material with a given ID
|
||||
|
||||
:param id: ID of the material
|
||||
:type id: int32_t
|
||||
:param index: Index in the materials array
|
||||
:type index: int32_t*
|
||||
:param int32_t id: ID of the material
|
||||
:param int32_t* index: Index in the materials array
|
||||
:return: Return status (negative if an error occurs)
|
||||
:rtype: int
|
||||
|
||||
.. c:function:: int openmc_get_nuclide_index(char name[], int* index)
|
||||
|
||||
Get the index in the nuclides array for a nuclide with a given name
|
||||
|
||||
:param char[] name: Name of the nuclide
|
||||
:param int* index: Index in the nuclides array
|
||||
:return: Return status (negative if an error occurs)
|
||||
:rtype: int
|
||||
|
||||
.. c:function:: int openmc_get_tally_index(int32_t id, int32_t* index)
|
||||
|
||||
Get the index in the tallies array for a tally with a given ID
|
||||
|
||||
:param int32_t id: ID of the tally
|
||||
:param int32_t* index: Index in the tallies array
|
||||
:return: Return status (negative if an error occurs)
|
||||
:rtype: int
|
||||
|
||||
|
|
@ -107,48 +269,42 @@ C API
|
|||
|
||||
Reset tallies, timers, and pseudo-random number generator state
|
||||
|
||||
.. c:function:: void openmc_init(int intracomm)
|
||||
.. c:function:: void openmc_init(const int* intracomm)
|
||||
|
||||
Initialize OpenMC
|
||||
|
||||
:param intracomm: MPI intracommunicator
|
||||
:type intracomm: int
|
||||
:param intracomm: MPI intracommunicator. If MPI is not being used, a null
|
||||
pointer should be passed.
|
||||
:type intracomm: const int*
|
||||
|
||||
.. c:function:: int openmc_load_nuclide(char name[])
|
||||
|
||||
Load data for a nuclide from the HDF5 data library.
|
||||
|
||||
:param name: Name of the nuclide.
|
||||
:type name: char[]
|
||||
:param char[] name: Name of the nuclide.
|
||||
:return: Return status (negative if an error occurs)
|
||||
:rtype: int
|
||||
|
||||
.. c:function:: int openmc_material_add_nuclide(int32_t index, char name[], double density)
|
||||
.. c:function:: int openmc_material_add_nuclide(int32_t index, const char name[], double density)
|
||||
|
||||
Add a nuclide to an existing material. If the nuclide already exists, the
|
||||
density is overwritten.
|
||||
|
||||
:param index: Index in the materials array
|
||||
:type index: int32_t
|
||||
:param int32_t index: Index in the materials array
|
||||
:param name: Name of the nuclide
|
||||
:type name: char[]
|
||||
:param density: Density in atom/b-cm
|
||||
:type density: double
|
||||
:type name: const char[]
|
||||
:param double density: Density in atom/b-cm
|
||||
:return: Return status (negative if an error occurs)
|
||||
:rtype: int
|
||||
|
||||
.. c:function:: int openmc_material_get_densities(int32_t index, int* nuclides[], double* densities[])
|
||||
.. c:function:: int openmc_material_get_densities(int32_t index, int** nuclides, double** densities, int* n)
|
||||
|
||||
Get density for each nuclide in a material.
|
||||
|
||||
:param index: Index in the materials array
|
||||
:type index: int32_t
|
||||
:param nuclides: Pointer to array of nuclide indices
|
||||
:type nuclides: int**
|
||||
:param densities: Pointer to the array of densities
|
||||
:type densities: double**
|
||||
:param n: Length of the array
|
||||
:type n: int
|
||||
:param int32_t index: Index in the materials array
|
||||
:param int** nuclides: Pointer to array of nuclide indices
|
||||
:param double** densities: Pointer to the array of densities
|
||||
:param int* n: Length of the array
|
||||
:return: Return status (negative if an error occurs)
|
||||
:rtype: int
|
||||
|
||||
|
|
@ -156,10 +312,8 @@ C API
|
|||
|
||||
Get the ID of a material
|
||||
|
||||
:param index: Index in the materials array
|
||||
:type index: int32_t
|
||||
:param id: ID of the material
|
||||
:type id: int32_t*
|
||||
:param int32_t index: Index in the materials array
|
||||
:param int32_t* id: ID of the material
|
||||
:return: Return status (negative if an error occurred)
|
||||
:rtype: int
|
||||
|
||||
|
|
@ -167,34 +321,75 @@ C API
|
|||
|
||||
Set the density of a material.
|
||||
|
||||
:param index: Index in the materials array
|
||||
:type index: int32_t
|
||||
:param density: Density of the material in atom/b-cm
|
||||
:type density: double
|
||||
:param int32_t index: Index in the materials array
|
||||
:param double density: Density of the material in atom/b-cm
|
||||
:return: Return status (negative if an error occurs)
|
||||
:rtype: int
|
||||
|
||||
.. c:function:: int openmc_material_set_densities(int32_t, n, char* name[], double density[])
|
||||
.. c:function:: int openmc_material_set_densities(int32_t index, int n, const char** name, const double density*)
|
||||
|
||||
:param index: Index in the materials array
|
||||
:type index: int32_t
|
||||
:param n: Length of name/density
|
||||
:type n: int
|
||||
:param int32_t index: Index in the materials array
|
||||
:param int n: Length of name/density
|
||||
:param name: Array of nuclide names
|
||||
:type name: char**
|
||||
:type name: const char**
|
||||
:param density: Array of densities
|
||||
:type density: double[]
|
||||
:type density: const double*
|
||||
:return: Return status (negative if an error occurs)
|
||||
:rtype: int
|
||||
|
||||
.. c:function:: int openmc_nuclide_name(int index, char* name[])
|
||||
.. c:function:: int openmc_material_set_id(int32_t index, int32_t id)
|
||||
|
||||
Set the ID of a material
|
||||
|
||||
:param int32_t index: Index in the materials array
|
||||
:param int32_t id: ID of the material
|
||||
:return: Return status (negative if an error occurred)
|
||||
:rtype: int
|
||||
|
||||
.. c:function:: int openmc_material_filter_get_bins(int32_t index, int32_t** bins, int32_t* n)
|
||||
|
||||
Get the bins for a material filter
|
||||
|
||||
:param int32_t index: Index in the filters array
|
||||
:param int32_t** bins: Index in the materials array for each bin
|
||||
:param int32_t* n: Number of bins
|
||||
:return: Return status (negative if an error occurred)
|
||||
:rtype: int
|
||||
|
||||
.. c:function:: int openmc_material_filter_set_bins(int32_t index, int32_t n, const int32_t* bins)
|
||||
|
||||
Set the bins for a material filter
|
||||
|
||||
:param int32_t index: Index in the filters array
|
||||
:param int32_t n: Number of bins
|
||||
:param bins: Index in the materials array for each bin
|
||||
:type bins: const int32_t*
|
||||
:return: Return status (negative if an error occurred)
|
||||
:rtype: int
|
||||
|
||||
.. c:function:: int openmc_mesh_filter_set_mesh(int32_t index, int32_t index_mesh)
|
||||
|
||||
Set the mesh for a mesh filter
|
||||
|
||||
:param int32_t index: Index in the filters array
|
||||
:param int32_t index_mesh: Index in the meshes array
|
||||
:return: Return status (negative if an error occurred)
|
||||
:rtype: int
|
||||
|
||||
.. c:function:: int openmc_next_batch()
|
||||
|
||||
Simulate next batch of particles. Must be called after openmc_simulation_init().
|
||||
|
||||
:return: Integer indicating whether simulation has finished (negative) or not
|
||||
finished (zero).
|
||||
:rtype: int
|
||||
|
||||
.. c:function:: int openmc_nuclide_name(int index, char** name)
|
||||
|
||||
Get name of a nuclide
|
||||
|
||||
:param index: Index in the nuclides array
|
||||
:type index: int
|
||||
:param name: Name of the nuclide
|
||||
:type name: char**
|
||||
:param int index: Index in the nuclides array
|
||||
:param char** name: Name of the nuclide
|
||||
:return: Return status (negative if an error occurs)
|
||||
:rtype: int
|
||||
|
||||
|
|
@ -210,27 +405,84 @@ C API
|
|||
|
||||
Run a simulation
|
||||
|
||||
.. c:function:: void openmc_simulation_finalize()
|
||||
|
||||
Finalize a simulation.
|
||||
|
||||
.. c:function:: void openmc_simulation_init()
|
||||
|
||||
Initialize a simulation. Must be called after openmc_init().
|
||||
|
||||
.. c:function:: int openmc_source_bank(struct Bank** ptr, int64_t* n)
|
||||
|
||||
Return a pointer to the source bank array.
|
||||
|
||||
:param ptr: Pointer to the source bank array
|
||||
:type ptr: struct Bank**
|
||||
:param int64_t* n: Length of the source bank array
|
||||
:return: Return status (negative if an error occurred)
|
||||
:rtype: int
|
||||
|
||||
.. c:function:: int openmc_source_set_strength(int32_t index, double strength)
|
||||
|
||||
Set the strength of an external source
|
||||
|
||||
:param int32_t index: Index in the external source array
|
||||
:param double strength: Source strength
|
||||
:return: Return status (negative if an error occurred)
|
||||
:rtype: int
|
||||
|
||||
.. c:function:: void openmc_statepoint_write(const char filename[])
|
||||
|
||||
Write a statepoint file
|
||||
|
||||
:param filename: Name of file to create. If a null pointer is passed, a
|
||||
filename is assigned automatically.
|
||||
:type filename: const char[]
|
||||
|
||||
.. c:function:: int openmc_tally_get_id(int32_t index, int32_t* id)
|
||||
|
||||
Get the ID of a tally
|
||||
|
||||
:param index: Index in the tallies array
|
||||
:type index: int32_t
|
||||
:param id: ID of the tally
|
||||
:type id: int32_t*
|
||||
:param int32_t index: Index in the tallies array
|
||||
:param int32_t* id: ID of the tally
|
||||
:return: Return status (negative if an error occurred)
|
||||
:rtype: int
|
||||
|
||||
.. c:function:: int openmc_tally_get_nuclides(int32_t index, int* nuclides[], int* n)
|
||||
.. c:function:: int openmc_tally_get_filters(int32_t index, int32_t** indices, int* n)
|
||||
|
||||
Get filters specified in a tally
|
||||
|
||||
:param int32_t index: Index in the tallies array
|
||||
:param int32_t** indices: Array of filter indices
|
||||
:param int* n: Number of filters
|
||||
:return: Return status (negative if an error occurred)
|
||||
:rtype: int
|
||||
|
||||
.. c:function:: int openmc_tally_get_n_realizations(int32_t index, int32_t* n)
|
||||
|
||||
:param int32_t index: Index in the tallies array
|
||||
:param int32_t* n: Number of realizations
|
||||
:return: Return status (negative if an error occurred)
|
||||
:rtype: int
|
||||
|
||||
.. c:function:: int openmc_tally_get_nuclides(int32_t index, int** nuclides, int* n)
|
||||
|
||||
Get nuclides specified in a tally
|
||||
|
||||
:param index: Index in the tallies array
|
||||
:type index: int32_t
|
||||
:param nuclides: Array of nuclide indices
|
||||
:type nuclides: int**
|
||||
:param n: Number of nuclides
|
||||
:type n: int*
|
||||
:param int32_t index: Index in the tallies array
|
||||
:param int** nuclides: Array of nuclide indices
|
||||
:param int* n: Number of nuclides
|
||||
:return: Return status (negative if an error occurred)
|
||||
:rtype: int
|
||||
|
||||
.. c:function:: int openmc_tally_get_scores(int32_t index, int** scores, int* n)
|
||||
|
||||
Get scores specified for a tally
|
||||
|
||||
:param int32_t index: Index in the tallies array
|
||||
:param int** scores: Array of scores
|
||||
:param int* n: Number of scores
|
||||
:return: Return status (negative if an error occurred)
|
||||
:rtype: int
|
||||
|
||||
|
|
@ -238,24 +490,50 @@ C API
|
|||
|
||||
Get a pointer to tally results array.
|
||||
|
||||
:param index: Index in the tallies array
|
||||
:type index: int32_t
|
||||
:param ptr: Pointer to the results array
|
||||
:type ptr: double**
|
||||
:param shape_: Shape of the results array
|
||||
:type shape_: int[3]
|
||||
:param int32_t index: Index in the tallies array
|
||||
:param double** ptr: Pointer to the results array
|
||||
:param int[3] shape_: Shape of the results array
|
||||
:return: Return status (negative if an error occurred)
|
||||
:rtype: int
|
||||
|
||||
.. c:function:: int openmc_tally_set_nuclides(int32_t index, int n, char* nuclides[])
|
||||
.. c:function:: int openmc_tally_set_filters(int32_t index, int n, const int32_t* indices)
|
||||
|
||||
Set filters for a tally
|
||||
|
||||
:param int32_t index: Index in the tallies array
|
||||
:param int n: Number of filters
|
||||
:param indices: Array of filter indices
|
||||
:type indices: const int32_t*
|
||||
:return: Return status (negative if an error occurred)
|
||||
:rtype: int
|
||||
|
||||
.. c:function:: int openmc_tally_set_id(int32_t index, int32_t id)
|
||||
|
||||
Set the ID of a tally
|
||||
|
||||
:param int32_t index: Index in the tallies array
|
||||
:param int32_t id: ID of the tally
|
||||
:return: Return status (negative if an error occurred)
|
||||
:rtype: int
|
||||
|
||||
.. c:function:: int openmc_tally_set_nuclides(int32_t index, int n, const char** nuclides)
|
||||
|
||||
Set the nuclides for a tally
|
||||
|
||||
:param index: Index in the tallies array
|
||||
:type index: int32_t
|
||||
:param n: Number of nuclides
|
||||
:type n: int
|
||||
:param int32_t index: Index in the tallies array
|
||||
:param int n: Number of nuclides
|
||||
:param nuclides: Array of nuclide names
|
||||
:type nuclides: char**
|
||||
:type nuclides: const char**
|
||||
:return: Return status (negative if an error occurred)
|
||||
:rtype: int
|
||||
|
||||
.. c:function:: int openmc_tally_set_scores(int32_t index, int n, const int* scores)
|
||||
|
||||
Set scores for a tally
|
||||
|
||||
:param int32_t index: Index in the tallies array
|
||||
:param int n: Number of scores
|
||||
:param scores: Array of scores
|
||||
:type scores: const int*
|
||||
:return: Return status (negative if an error occurred)
|
||||
:rtype: int
|
||||
|
|
|
|||
|
|
@ -18,19 +18,21 @@ on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
|
|||
|
||||
# On Read the Docs, we need to mock a few third-party modules so we don't get
|
||||
# ImportErrors when building documentation
|
||||
try:
|
||||
from unittest.mock import MagicMock
|
||||
except ImportError:
|
||||
from mock import Mock as MagicMock
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
|
||||
MOCK_MODULES = ['numpy', 'numpy.polynomial', 'numpy.polynomial.polynomial',
|
||||
'numpy.ctypeslib', 'scipy', 'scipy.sparse', 'scipy.interpolate',
|
||||
'scipy.integrate', 'scipy.optimize', 'scipy.special', 'h5py',
|
||||
'pandas', 'uncertainties', 'openmoc', 'openmc.data.reconstruct']
|
||||
MOCK_MODULES = [
|
||||
'numpy', 'numpy.polynomial', 'numpy.polynomial.polynomial',
|
||||
'numpy.ctypeslib', 'scipy', 'scipy.sparse', 'scipy.sparse.linalg',
|
||||
'scipy.interpolate', 'scipy.integrate', 'scipy.optimize', 'scipy.special',
|
||||
'scipy.stats', 'scipy.spatial', 'h5py', 'pandas', 'uncertainties',
|
||||
'matplotlib', 'matplotlib.pyplot', 'openmoc',
|
||||
'openmc.data.reconstruct'
|
||||
]
|
||||
sys.modules.update((mod_name, MagicMock()) for mod_name in MOCK_MODULES)
|
||||
|
||||
import numpy as np
|
||||
np.ndarray = MagicMock
|
||||
np.polynomial.Polynomial = MagicMock
|
||||
|
||||
|
||||
|
|
@ -51,6 +53,7 @@ extensions = ['sphinx.ext.autodoc',
|
|||
'sphinx.ext.autosummary',
|
||||
'sphinx.ext.intersphinx',
|
||||
'sphinx.ext.viewcode',
|
||||
'sphinx.ext.imgconverter',
|
||||
'sphinx_numfig',
|
||||
'notebook_sphinxext']
|
||||
|
||||
|
|
@ -68,16 +71,16 @@ master_doc = 'index'
|
|||
|
||||
# General information about the project.
|
||||
project = u'OpenMC'
|
||||
copyright = u'2011-2017, Massachusetts Institute of Technology'
|
||||
copyright = u'2011-2018, Massachusetts Institute of Technology'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = "0.9"
|
||||
version = "0.10"
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = "0.9.0"
|
||||
release = "0.10.0"
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
|
@ -251,6 +254,6 @@ napoleon_use_ivar = True
|
|||
intersphinx_mapping = {
|
||||
'python': ('https://docs.python.org/3', None),
|
||||
'numpy': ('https://docs.scipy.org/doc/numpy/', None),
|
||||
'pandas': ('http://pandas.pydata.org/pandas-docs/stable/', None),
|
||||
'matplotlib': ('http://matplotlib.org/', None)
|
||||
'pandas': ('https://pandas.pydata.org/pandas-docs/stable/', None),
|
||||
'matplotlib': ('https://matplotlib.org/', None)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,15 +5,16 @@ Building Sphinx Documentation
|
|||
=============================
|
||||
|
||||
In order to build the documentation in the ``docs`` directory, you will need to
|
||||
have the Sphinx_ third-party Python package. The easiest way to install Sphinx
|
||||
is via pip:
|
||||
have the `Sphinx <http://openmc.readthedocs.io/en/latest/>`_ third-party Python
|
||||
package. The easiest way to install Sphinx is via pip:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
sudo pip install sphinx
|
||||
|
||||
Additionally, you will also need a Sphinx extension for numbering figures. The
|
||||
Numfig_ package can be installed directly with pip:
|
||||
`Numfig <http://openmc.readthedocs.io/en/latest/>`_ package can be installed
|
||||
directly with pip:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
|
|
@ -24,7 +25,7 @@ Building Documentation as a Webpage
|
|||
-----------------------------------
|
||||
|
||||
To build the documentation as a webpage (what appears at
|
||||
http://mit-crpg.github.io/openmc), simply go to the ``docs`` directory and run:
|
||||
http://openmc.readthedocs.io), simply go to the ``docs`` directory and run:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
|
|
@ -35,21 +36,9 @@ Building Documentation as a PDF
|
|||
-------------------------------
|
||||
|
||||
To build PDF documentation, you will need to have a LaTeX distribution installed
|
||||
on your computer as well as Inkscape_, which is used to convert .svg files to
|
||||
.pdf files. Inkscape can be installed in a Debian-derivative with:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
sudo apt-get install inkscape
|
||||
|
||||
One the pre-requisites are installed, simply go to the ``docs`` directory and
|
||||
run:
|
||||
on your computer. Once you have a LaTeX distribution installed, simply go to the
|
||||
``docs`` directory and run:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
make latexpdf
|
||||
|
||||
.. _Sphinx: http://sphinx-doc.org
|
||||
.. _sphinxcontrib-tikz: https://bitbucket.org/philexander/tikz
|
||||
.. _Numfig: https://pypi.python.org/pypi/sphinx_numfig
|
||||
.. _Inkscape: https://inkscape.org
|
||||
|
|
|
|||
|
|
@ -10,10 +10,10 @@ as debugging.
|
|||
|
||||
.. toctree::
|
||||
:numbered:
|
||||
:maxdepth: 3
|
||||
:maxdepth: 2
|
||||
|
||||
structures
|
||||
styleguide
|
||||
workflow
|
||||
tests
|
||||
user-input
|
||||
docbuild
|
||||
|
|
|
|||
|
|
@ -1,155 +0,0 @@
|
|||
.. _devguide_structures:
|
||||
|
||||
===============
|
||||
Data Structures
|
||||
===============
|
||||
|
||||
The purpose of this section is to give you an overview of the major data
|
||||
structures in OpenMC and how they are logically related. A majority of variables
|
||||
in OpenMC are `derived types`_ (similar to a struct in C). These derived types
|
||||
are defined in the various header modules, e.g. src/geometry_header.F90. Most
|
||||
important variables are found in the `global module`_. Have a look through that
|
||||
module to get a feel for what variables you'll often come across when looking at
|
||||
OpenMC code.
|
||||
|
||||
--------
|
||||
Particle
|
||||
--------
|
||||
|
||||
Perhaps the variable that you will see most often is simply called ``p`` and is
|
||||
of type(Particle). This variable stores information about a particle's physical
|
||||
characteristics (coordinates, direction, energy), what cell and material it's
|
||||
currently in, how many collisions it has undergone, etc. In practice, only one
|
||||
particle is followed at a time so there is no array of type(Particle). The
|
||||
Particle type is defined in the `particle_header module`_.
|
||||
|
||||
You will notice that the direction and angle of the particle is stored in a
|
||||
linked list of type(LocalCoord). In geometries with multiple :ref:`universes`,
|
||||
the coordinates in each universe are stored in this linked list. If universes or
|
||||
lattices are not used in a geometry, only one LocalCoord is present in the
|
||||
linked list.
|
||||
|
||||
The LocalCoord type has a component called cell which gives the index in the
|
||||
``cells`` array in the `global module`_. The ``cells`` array is of type(Cell)
|
||||
and stored information about each region defined by the user.
|
||||
|
||||
----
|
||||
Cell
|
||||
----
|
||||
|
||||
The Cell type is defined in the `geometry_header module`_ along with other
|
||||
geometry-related derived types. Each cell in the problem is described in terms
|
||||
of its bounding surfaces, which are listed on the ``surfaces`` component. The
|
||||
absolute value of each item in the ``surfaces`` component contains the index of
|
||||
the corresponding surface in the ``surfaces`` array defined in the `global
|
||||
module`_. The sign on each item in the ``surfaces`` component indicates whether
|
||||
the cell exists on the positive or negative side of the surface (see
|
||||
:ref:`methods_geometry`).
|
||||
|
||||
Each cell can either be filled with another universe/lattice or with a
|
||||
material. If it is filled with a material, the ``material`` component gives the
|
||||
index of the material in the ``materials`` array defined in the `global
|
||||
module`_.
|
||||
|
||||
-------
|
||||
Surface
|
||||
-------
|
||||
|
||||
The Surface type is defined in the `geometry_header module`_. A surface is
|
||||
defined by a type (sphere, cylinder, etc.) and a list of coefficients for that
|
||||
surface type. The simplest example would be a plane perpendicular to the xy, yz,
|
||||
or xz plane which needs only one parameter. The ``type`` component indicates the
|
||||
type through integer parameters such as SURF_SPHERE or SURF_CYL_Y (these are
|
||||
defined in the `constants module`_). The ``coeffs`` component gives the
|
||||
necessary coefficients to parameterize the surface type (see
|
||||
:ref:`surface_element`).
|
||||
|
||||
--------
|
||||
Material
|
||||
--------
|
||||
|
||||
The Material type is defined in the `material_header module`_. Each material
|
||||
contains a number of nuclides at a given atom density. Each item in the
|
||||
``nuclide`` component corresponds to the index in the global ``nuclides`` array
|
||||
(as usual, found in the `global module`_). The ``atom_density`` component is the
|
||||
same length as the ``nuclides`` component and lists the corresponding atom
|
||||
density in atom/barn-cm for each nuclide in the ``nuclides`` component.
|
||||
|
||||
If the material contains nuclides for which binding effects are important in
|
||||
low-energy scattering, a :math:`S(\alpha,\beta)` can be associated with that
|
||||
material through the ``sab_table`` component. Again, this component contains the
|
||||
index in the ``sab_tables`` array from the `global module`_.
|
||||
|
||||
-------
|
||||
Nuclide
|
||||
-------
|
||||
|
||||
The Nuclide derived type stores cross section and interaction data for a nucleus
|
||||
and is defined in the `ace_header module`_. The ``energy`` component is an array
|
||||
that gives the discrete energies at which microscopic cross sections are
|
||||
tabulated. The actual microscopic cross sections are stored in a separate
|
||||
derived type, Reaction. An arrays of Reactions is present in the ``reactions``
|
||||
component. There are a few summary microscopic cross sections stored in other
|
||||
components, such as ``total``, ``elastic``, ``fission``, and ``nu_fission``.
|
||||
|
||||
If a Nuclide is fissionable, the prompt and delayed neutron yield and energy
|
||||
distributions are also stored on the Nuclide type. Many nuclides also have
|
||||
unresolved resonance probability table data. If present, this data is stored in
|
||||
the component ``urr_data`` of derived type UrrData. A complete description of
|
||||
the probability table method is given in :ref:`probability_tables`.
|
||||
|
||||
The list of nuclides present in a problem is stored in the ``nuclides`` array
|
||||
defined in the `global module`_.
|
||||
|
||||
----------
|
||||
SAlphaBeta
|
||||
----------
|
||||
|
||||
The SAlphaBeta derived type stores :math:`S(\alpha,\beta)` data to account for
|
||||
molecular binding effects when treating thermal scattering. Each SAlphaBeta
|
||||
table is associated with a specific nuclide as identified in the ``zaid``
|
||||
component. A complete description of the :math:`S(\alpha,\beta)` treatment can
|
||||
be found in :ref:`sab_tables`.
|
||||
|
||||
---------
|
||||
XsListing
|
||||
---------
|
||||
|
||||
The XsListing derived type stores information on the location of an ACE cross
|
||||
section table based on the data in cross_sections.xml and is defined in the
|
||||
`ace_header module`_. For each ``<ace_table>`` you see in cross_sections.xml,
|
||||
there is a XsListing with its information. When the user input is read, the
|
||||
array ``xs_listings`` in the `global module`_ that is of derived type XsListing
|
||||
is used to locate the ACE data to parse.
|
||||
|
||||
--------------
|
||||
NuclideMicroXS
|
||||
--------------
|
||||
|
||||
The NuclideMicroXS derived type, defined in the `ace_header module`_, acts as a
|
||||
'cache' for microscopic cross sections. As a particle is traveling through
|
||||
different materials, cross sections can be reused if the energy of the particle
|
||||
hasn't changed. The components ``total``, ``elastic``, ``absorption``,
|
||||
``fission``, and ``nu_fission`` represent those microscopic cross sections at
|
||||
the current energy of the particle for a given nuclide. An array ``micro_xs`` in
|
||||
the `global module`_ that is the same length as the ``nuclides`` array stores
|
||||
these cached cross sections for each nuclide in the problem.
|
||||
|
||||
---------------
|
||||
MaterialMacroXS
|
||||
---------------
|
||||
|
||||
In addition to the NuclideMicroXS type, there is also a MaterialMacroXS derived
|
||||
type, defined in the `ace_header module`_ that stored cached *macroscopic* cross
|
||||
sections for the current material. These macroscopic cross sections are used for
|
||||
both physics and tallying purposes. The variable ``material_xs`` in the `global
|
||||
module`_ is of type MaterialMacroXS.
|
||||
|
||||
|
||||
.. _derived types: http://nf.nci.org.au/training/FortranAdvanced/slides/slides.025.html
|
||||
.. _global module: https://github.com/mit-crpg/openmc/blob/master/src/global.F90
|
||||
.. _particle_header module: https://github.com/mit-crpg/openmc/blob/master/src/particle_header.F90
|
||||
.. _geometry_header module: https://github.com/mit-crpg/openmc/blob/master/src/geometry_header.F90
|
||||
.. _constants module: https://github.com/mit-crpg/openmc/blob/master/src/constants.F90
|
||||
.. _material_header module: https://github.com/mit-crpg/openmc/blob/master/src/material_header.F90
|
||||
.. _ace_header module: https://github.com/mit-crpg/openmc/blob/master/src/ace_header.F90
|
||||
|
|
@ -12,21 +12,18 @@ adding new code in OpenMC.
|
|||
Fortran
|
||||
-------
|
||||
|
||||
General Rules
|
||||
Miscellaneous
|
||||
-------------
|
||||
|
||||
Conform to the Fortran 2008 standard.
|
||||
|
||||
Make sure code can be compiled with most common compilers, especially gfortran
|
||||
and the Intel Fortran compiler. This supercedes the previous rule --- if a
|
||||
and the Intel Fortran compiler. This supersedes the previous rule --- if a
|
||||
Fortran 2003/2008 feature is not implemented in a common compiler, do not use
|
||||
it.
|
||||
|
||||
Do not use special extensions that can be only be used from certain compilers.
|
||||
|
||||
In general, write your code in lower-case. Having code in all caps does not
|
||||
enhance code readability or otherwise.
|
||||
|
||||
Always include comments to describe what your code is doing. Do not be afraid of
|
||||
using copious amounts of comments.
|
||||
|
||||
|
|
@ -38,6 +35,28 @@ Don't use ``print *`` or ``write(*,*)``. If writing to a file, use a specific
|
|||
unit. Writing to standard output or standard error should be handled by the
|
||||
``write_message`` subroutine or functionality in the error module.
|
||||
|
||||
Naming
|
||||
------
|
||||
|
||||
In general, write your code in lower-case. Having code in all caps does not
|
||||
enhance code readability or otherwise.
|
||||
|
||||
Module names should be lower-case with underscores if needed, e.g.
|
||||
``xml_interface``.
|
||||
|
||||
Class names should be CamelCase, e.g. ``HexLattice``.
|
||||
|
||||
Functions and subroutines (including type-bound methods) should be lower-case
|
||||
with underscores, e.g. ``get_indices``.
|
||||
|
||||
Local variables, global variables, and type attributes should be lower-case
|
||||
with underscores (e.g. ``n_cells``) except for physics symbols that are written
|
||||
differently by convention (e.g. ``E`` for energy).
|
||||
|
||||
Constant (parameter) variables should be in upper-case with underscores, e.g.
|
||||
``SQRT_PI``. If they are used by more than one module, define them in the
|
||||
constants.F90 module.
|
||||
|
||||
Procedures
|
||||
----------
|
||||
|
||||
|
|
@ -55,18 +74,10 @@ Variables
|
|||
Never, under any circumstances, should implicit variables be used! Always
|
||||
include ``implicit none`` and define all your variables.
|
||||
|
||||
Variable names should be all lower-case and descriptive, i.e. not a random
|
||||
assortment of letters that doesn't give any information to someone seeing it for
|
||||
the first time. Variables consisting of multiple words should be separated by
|
||||
underscores, not hyphens or in camel case.
|
||||
|
||||
Constant (parameter) variables should be in ALL CAPITAL LETTERS and defined in
|
||||
in the constants.F90 module.
|
||||
|
||||
32-bit reals (real(4)) should never be used. Always use 64-bit reals (real(8)).
|
||||
|
||||
For arbitrary length character variables, use the pre-defined lengths
|
||||
MAX_LINE_LEN, MAX_WORD_LEN, and MAX_FILE_LEN if possible.
|
||||
``MAX_LINE_LEN``, ``MAX_WORD_LEN``, and ``MAX_FILE_LEN`` if possible.
|
||||
|
||||
Do not use old-style character/array length (e.g. character*80, real*8).
|
||||
|
||||
|
|
@ -92,7 +103,7 @@ allocation instead. Use allocatable variables instead of pointer variables when
|
|||
possible.
|
||||
|
||||
Shared/Module Variables
|
||||
+++++++++++++++++++++++
|
||||
-----------------------
|
||||
|
||||
Always put shared variables in modules. Access module variables through a
|
||||
``use`` statement. Always use the ``only`` specifier on the ``use`` statement
|
||||
|
|
@ -100,12 +111,6 @@ except for variables from the global, constants, and various header modules.
|
|||
|
||||
Never use ``equivalence`` statements, ``common`` blocks, or ``data`` statements.
|
||||
|
||||
Derived Types and Classes
|
||||
-------------------------
|
||||
|
||||
Derived types and classes should have CamelCase names with words not separated
|
||||
by underscores or hyphens.
|
||||
|
||||
Indentation
|
||||
-----------
|
||||
|
||||
|
|
@ -158,6 +163,120 @@ each side.
|
|||
|
||||
Do not leave trailing whitespace at the end of a line.
|
||||
|
||||
---
|
||||
C++
|
||||
---
|
||||
|
||||
Miscellaneous
|
||||
-------------
|
||||
|
||||
Follow the `C++ Core Guidelines`_ except when they conflict with another
|
||||
guideline listed here. For convenience, many important guidelines from that
|
||||
list are repeated here.
|
||||
|
||||
Conform to the C++11 standard. Note that this is a significant difference
|
||||
between our style and the C++ Core Guidelines. Many suggestions in those
|
||||
Guidelines require C++14.
|
||||
|
||||
Always use C++-style comments (``//``) as opposed to C-style (``/**/``). (It
|
||||
is more difficult to comment out a large section of code that uses C-style
|
||||
comments.)
|
||||
|
||||
Header files should always use include guards with the following style (See
|
||||
`SF.8 <http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#sf8-use-include-guards-for-all-h-files>`_:
|
||||
|
||||
.. code-block:: C++
|
||||
|
||||
#ifndef MODULE_NAME_H
|
||||
#define MODULE_NAME_H
|
||||
...
|
||||
content
|
||||
...
|
||||
#endif // MODULE_NAME_H
|
||||
|
||||
Do not use C-style casting. Always use the C++-style casts ``static_cast``,
|
||||
``const_cast``, or ``reinterpret_cast``. (See `ES.49 <http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#es49-if-you-must-use-a-cast-use-a-named-cast>`_)
|
||||
|
||||
Naming
|
||||
------
|
||||
|
||||
In general, write your code in lower-case. Having code in all caps does not
|
||||
enhance code readability or otherwise.
|
||||
|
||||
Struct and class names should be CamelCase, e.g. ``HexLattice``.
|
||||
|
||||
Functions (including member functions) should be lower-case with underscores,
|
||||
e.g. ``get_indices``.
|
||||
|
||||
Local variables, global variables, and struct/class attributes should be
|
||||
lower-case with underscores (e.g. ``n_cells``) except for physics symbols that
|
||||
are written differently by convention (e.g. ``E`` for energy).
|
||||
|
||||
Const variables should be in upper-case with underscores, e.g. ``SQRT_PI``.
|
||||
|
||||
Curly braces
|
||||
------------
|
||||
|
||||
For a function definition, the opening and closing braces should each be on
|
||||
their own lines. This helps distinguish function code from the argument list.
|
||||
If the entire function fits on one line, then the braces can be on the same
|
||||
line. e.g.:
|
||||
|
||||
.. code-block:: C++
|
||||
|
||||
return_type function(type1 arg1, type2 arg2)
|
||||
{
|
||||
content();
|
||||
}
|
||||
|
||||
return_type
|
||||
function_with_many_args(type1 arg1, type2 arg2, type3 arg3,
|
||||
type4 arg4)
|
||||
{
|
||||
content();
|
||||
}
|
||||
|
||||
int return_one() {return 1;}
|
||||
|
||||
For a conditional, the opening brace should be on the same line as the end of
|
||||
the conditional statement. If there is a following ``else if`` or ``else``
|
||||
statement, the closing brace should be on the same line as that following
|
||||
statement. Otherwise, the closing brace should be on its own line. A one-line
|
||||
conditional can have the closing brace on the same line or it can omit the
|
||||
braces entirely e.g.:
|
||||
|
||||
.. code-block:: C++
|
||||
|
||||
if (condition) {
|
||||
content();
|
||||
}
|
||||
|
||||
if (condition1) {
|
||||
content();
|
||||
} else if (condition 2) {
|
||||
more_content();
|
||||
} else {
|
||||
further_content();
|
||||
}
|
||||
|
||||
if (condition) {content()};
|
||||
|
||||
if (condition) content();
|
||||
|
||||
For loops similarly have an opening brace on the same line as the statement and
|
||||
a closing brace on its own line. One-line loops may have the closing brace on
|
||||
the same line or omit the braces entirely.
|
||||
|
||||
.. code-block:: C++
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
content();
|
||||
}
|
||||
|
||||
for (int i = 0; i < 5; i++) {content();}
|
||||
|
||||
for (int i = 0; i < 5; i++) content();
|
||||
|
||||
------
|
||||
Python
|
||||
------
|
||||
|
|
@ -172,6 +291,7 @@ Use of third-party Python packages should be limited to numpy_, scipy_, and
|
|||
h5py_. Use of other third-party packages must be implemented as optional
|
||||
dependencies rather than required dependencies.
|
||||
|
||||
.. _C++ Core Guidelines: http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines
|
||||
.. _PEP8: https://www.python.org/dev/peps/pep-0008/
|
||||
.. _numpydoc: https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt
|
||||
.. _numpy: http://www.numpy.org/
|
||||
|
|
|
|||
73
docs/source/devguide/tests.rst
Normal file
73
docs/source/devguide/tests.rst
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
.. _devguide_tests:
|
||||
|
||||
==========
|
||||
Test Suite
|
||||
==========
|
||||
|
||||
Running Tests
|
||||
-------------
|
||||
|
||||
The OpenMC test suite consists of two parts, a regression test suite and a unit
|
||||
test suite. The regression test suite is based on regression or integrated
|
||||
testing where different types of input files are configured and the full OpenMC
|
||||
code is executed. Results from simulations are compared with expected
|
||||
results. The unit tests are primarily intended to test individual
|
||||
functions/classes in the OpenMC Python API.
|
||||
|
||||
The test suite relies on the third-party `pytest <https://pytest.org>`_
|
||||
package. To run either or both the regression and unit test suites, it is
|
||||
assumed that you have OpenMC fully installed, i.e., the :ref:`scripts_openmc`
|
||||
executable is available on your :envvar:`PATH` and the :mod:`openmc` Python
|
||||
module is importable. In development where it would be onerous to continually
|
||||
install OpenMC every time a small change is made, it is recommended to install
|
||||
OpenMC in development/editable mode. With setuptools, this is accomplished by
|
||||
running::
|
||||
|
||||
python setup.py develop
|
||||
|
||||
or using pip (recommended)::
|
||||
|
||||
pip install -e .[test]
|
||||
|
||||
It is also assumed that you have cross section data available that is pointed to
|
||||
by the :envvar:`OPENMC_CROSS_SECTIONS` and :envvar:`OPENMC_MULTIPOLE_LIBRARY`
|
||||
environment variables. Furthermore, to run unit tests for the :mod:`openmc.data`
|
||||
module, it is necessary to have ENDF/B-VII.1 data available and pointed to by
|
||||
the :envvar:`OPENMC_ENDF_DATA` environment variable. All data sources can be
|
||||
obtained using the ``tools/ci/travis-before-script.sh`` script.
|
||||
|
||||
To execute the test suite, go to the ``tests/`` directory and run::
|
||||
|
||||
pytest
|
||||
|
||||
If you want to collect information about source line coverage in the Python API,
|
||||
you must have the `pytest-cov <https://pypi.python.org/pypi/pytest-cov>`_ plugin
|
||||
installed and run::
|
||||
|
||||
pytest --cov=../openmc --cov-report=html
|
||||
|
||||
Adding Tests to the Regression Suite
|
||||
------------------------------------
|
||||
|
||||
To add a new test to the regression test suite, create a sub-directory in the
|
||||
``tests/regression_tests/`` directory. To configure a test you need to add the
|
||||
following files to your new test directory:
|
||||
|
||||
* OpenMC input XML files, if they are not generated through the Python API
|
||||
* **test.py** - Python test driver script; please refer to other tests to
|
||||
see how to construct. Any output files that are generated during testing
|
||||
must be removed at the end of this script.
|
||||
* **inputs_true.dat** - ASCII file that contains Python API-generated XML
|
||||
files concatenated together. When the test is run, inputs that are
|
||||
generated are compared to this file.
|
||||
* **results_true.dat** - ASCII file that contains the expected results from
|
||||
the test. The file *results_test.dat* is compared to this file during the
|
||||
execution of the python test driver script. When the above files have been
|
||||
created, generate a *results_test.dat* file and copy it to this name and
|
||||
commit. It should be noted that this file should be generated with basic
|
||||
compiler options during openmc configuration and build (e.g., no MPI, no
|
||||
debug/optimization).
|
||||
|
||||
In addition to this description, please see the various types of tests that are
|
||||
already included in the test suite to see how to create them. If all is
|
||||
implemented correctly, the new test will automatically be discovered by pytest.
|
||||
|
|
@ -89,139 +89,6 @@ features and bug fixes. The general steps for contributing are as follows:
|
|||
6. After the pull request has been thoroughly vetted, it is merged back into the
|
||||
*develop* branch of mit-crpg/openmc.
|
||||
|
||||
.. _test suite:
|
||||
|
||||
OpenMC Test Suite
|
||||
-----------------
|
||||
|
||||
The purpose of this test suite is to ensure that OpenMC compiles using various
|
||||
combinations of compiler flags and options, and that all user input options can
|
||||
be used successfully without breaking the code. The test suite is comprised of
|
||||
regression tests where different types of input files are configured and the
|
||||
full OpenMC code is executed. Results from simulations are compared with
|
||||
expected results. The test suite is comprised of many build configurations
|
||||
(e.g. debug, mpi, hdf5) and the actual tests which reside in sub-directories
|
||||
in the tests directory. We recommend to developers to test their branches
|
||||
before submitting a formal pull request using gfortran and Intel compilers
|
||||
if available.
|
||||
|
||||
The test suite is designed to integrate with cmake using ctest_. It is
|
||||
configured to run with cross sections from NNDC_ augmented with 0 K elastic
|
||||
scattering data for select nuclides as well as multipole data. To download the
|
||||
proper data, run the following commands:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
wget -O nndc_hdf5.tar.xz $(cat <openmc_root>/.travis.yml | grep anl.box | awk '{print $2}')
|
||||
tar xJvf nndc_hdf5.tar.xz
|
||||
export OPENMC_CROSS_SECTIONS=$(pwd)/nndc_hdf5/cross_sections.xml
|
||||
|
||||
git clone --branch=master git://github.com/smharper/windowed_multipole_library.git wmp_lib
|
||||
tar xzvf wmp_lib/multipole_lib.tar.gz
|
||||
export OPENMC_MULTIPOLE_LIBRARY=$(pwd)/multipole_lib
|
||||
|
||||
The test suite can be run on an already existing build using:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
cd build
|
||||
make test
|
||||
|
||||
or
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
cd build
|
||||
ctest
|
||||
|
||||
There are numerous ctest_ command line options that can be set to have
|
||||
more control over which tests are executed.
|
||||
|
||||
Before running the test suite python script, the following environmental
|
||||
variables should be set if the default paths are incorrect:
|
||||
|
||||
* **FC** - The command for a Fortran compiler (e.g. gfotran, ifort).
|
||||
|
||||
* Default - *gfortran*
|
||||
|
||||
* **CC** - The command for a C compiler (e.g. gcc, icc).
|
||||
|
||||
* Default - *gcc*
|
||||
|
||||
* **CXX** - The command for a C++ compiler (e.g. g++, icpc).
|
||||
|
||||
* Default - *g++*
|
||||
|
||||
* **MPI_DIR** - The path to the MPI directory.
|
||||
|
||||
* Default - */opt/mpich/3.2-gnu*
|
||||
|
||||
* **HDF5_DIR** - The path to the HDF5 directory.
|
||||
|
||||
* Default - */opt/hdf5/1.8.16-gnu*
|
||||
|
||||
* **PHDF5_DIR** - The path to the parallel HDF5 directory.
|
||||
|
||||
* Default - */opt/phdf5/1.8.16-gnu*
|
||||
|
||||
To run the full test suite, the following command can be executed in the
|
||||
tests directory:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
python run_tests.py
|
||||
|
||||
A subset of build configurations and/or tests can be run. To see how to use
|
||||
the script run:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
python run_tests.py --help
|
||||
|
||||
As an example, say we want to run all tests with debug flags only on tests
|
||||
that have cone and plot in their name. Also, we would like to run this on
|
||||
4 processors. We can run:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
python run_tests.py -j 4 -C debug -R "cone|plot"
|
||||
|
||||
Note that standard regular expression syntax is used for selecting build
|
||||
configurations and tests. To print out a list of build configurations, we
|
||||
can run:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
python run_tests.py -p
|
||||
|
||||
Adding tests to test suite
|
||||
++++++++++++++++++++++++++
|
||||
|
||||
To add a new test to the test suite, create a sub-directory in the tests
|
||||
directory that conforms to the regular expression *test_*. To configure
|
||||
a test you need to add the following files to your new test directory,
|
||||
*test_name* for example:
|
||||
|
||||
* OpenMC input XML files
|
||||
* **test_name.py** - Python test driver script, please refer to other
|
||||
tests to see how to construct. Any output files that are generated
|
||||
during testing must be removed at the end of this script.
|
||||
* **inputs_true.dat** - ASCII file that contains Python API-generated XML
|
||||
files concatenated together. When the test is run, inputs that are
|
||||
generated are compared to this file.
|
||||
* **results_true.dat** - ASCII file that contains the expected results
|
||||
from the test. The file *results_test.dat* is compared to this file
|
||||
during the execution of the python test driver script. When the
|
||||
above files have been created, generate a *results_test.dat* file and
|
||||
copy it to this name and commit. It should be noted that this file
|
||||
should be generated with basic compiler options during openmc
|
||||
configuration and build (e.g., no MPI/HDF5, no debug/optimization).
|
||||
|
||||
In addition to this description, please see the various types of tests that
|
||||
are already included in the test suite to see how to create them. If all is
|
||||
implemented correctly, the new test directory will automatically be added
|
||||
to the CTest framework.
|
||||
|
||||
Private Development
|
||||
-------------------
|
||||
|
||||
|
|
@ -236,6 +103,27 @@ changes you've made in your private repository back to mit-crpg/openmc
|
|||
repository, simply follow the steps above with an extra step of pulling a branch
|
||||
from your private repository into a public fork.
|
||||
|
||||
.. _devguide_editable:
|
||||
|
||||
Working in "Development" Mode
|
||||
-----------------------------
|
||||
|
||||
If you are making changes to the Python API during development, it is highly
|
||||
suggested to install the Python API in development/editable mode using
|
||||
pip_. From the root directory of the OpenMC repository, run:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
pip install -e .[test]
|
||||
|
||||
This installs the OpenMC Python package in `"editable" mode
|
||||
<https://pip.pypa.io/en/stable/reference/pip_install/#editable-installs>`_ so
|
||||
that 1) it can be imported from a Python interpreter and 2) any changes made are
|
||||
immediately reflected in the installed version (that is, you don't need to keep
|
||||
reinstalling it). While the same effect can be achieved using the
|
||||
:envvar:`PYTHONPATH` environment variable, this is generally discouraged as it
|
||||
can interfere with virtual environments.
|
||||
|
||||
.. _git: http://git-scm.com/
|
||||
.. _GitHub: https://github.com/
|
||||
.. _git flow: http://nvie.com/git-model
|
||||
|
|
@ -247,3 +135,4 @@ from your private repository into a public fork.
|
|||
.. _Bitbucket: https://bitbucket.org
|
||||
.. _ctest: http://www.cmake.org/cmake/help/v2.8.12/ctest.html
|
||||
.. _NNDC: http://www.nndc.bnl.gov/endf/b7.1/acefiles.html
|
||||
.. _pip: https://pip.pypa.io/en/stable/
|
||||
|
|
|
|||
|
|
@ -10,21 +10,25 @@ interaction data is based on a native HDF5 format that can be generated from ACE
|
|||
files used by the MCNP and Serpent Monte Carlo codes.
|
||||
|
||||
OpenMC was originally developed by members of the `Computational Reactor Physics
|
||||
Group`_ at the `Massachusetts Institute of Technology`_ starting
|
||||
in 2011. Various universities, laboratories, and other organizations now
|
||||
contribute to the development of OpenMC. For more information on OpenMC, feel
|
||||
free to send a message to the User's Group `mailing list`_.
|
||||
Group <http://crpg.mit.edu>`_ at the `Massachusetts Institute of Technology
|
||||
<http://web.mit.edu>`_ starting in 2011. Various universities, laboratories, and
|
||||
other organizations now contribute to the development of OpenMC. For more
|
||||
information on OpenMC, feel free to send a message to the User's Group `mailing
|
||||
list <https://groups.google.com/forum/?fromgroups=#!forum/openmc-users>`_.
|
||||
|
||||
.. _Computational Reactor Physics Group: http://crpg.mit.edu
|
||||
.. _Massachusetts Institute of Technology: http://web.mit.edu
|
||||
.. _mailing list: https://groups.google.com/forum/?fromgroups=#!forum/openmc-users
|
||||
.. _Read the Docs: http://openmc.readthedocs.io/en/latest/
|
||||
.. admonition:: Recommended publication for citing
|
||||
:class: tip
|
||||
|
||||
Paul K. Romano, Nicholas E. Horelik, Bryan R. Herman, Adam G. Nelson, Benoit
|
||||
Forget, and Kord Smith, "`OpenMC: A State-of-the-Art Monte Carlo Code for
|
||||
Research and Development <https://doi.org/10.1016/j.anucene.2014.07.048>`_,"
|
||||
*Ann. Nucl. Energy*, **82**, 90--97 (2015).
|
||||
|
||||
.. only:: html
|
||||
|
||||
--------
|
||||
Contents
|
||||
--------
|
||||
--------
|
||||
Contents
|
||||
--------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
|
|
|||
102
docs/source/io_formats/depletion_chain.rst
Normal file
102
docs/source/io_formats/depletion_chain.rst
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
.. _io_depletion_chain:
|
||||
|
||||
============================
|
||||
Depletion Chain -- chain.xml
|
||||
============================
|
||||
|
||||
A depletion chain file has a ``<depletion_chain>`` root element with one or more
|
||||
``<nuclide>`` child elements. The decay, reaction, and fission product data for
|
||||
each nuclide appears as child elements of ``<nuclide>``.
|
||||
|
||||
---------------------
|
||||
``<nuclide>`` Element
|
||||
---------------------
|
||||
|
||||
The ``<nuclide>`` element contains information on the decay modes, reactions,
|
||||
and fission product yields for a given nuclide in the depletion chain. This
|
||||
element may have the following attributes:
|
||||
|
||||
:name:
|
||||
Name of the nuclide
|
||||
|
||||
:half_life:
|
||||
Half-life of the nuclide in [s]
|
||||
|
||||
:decay_modes:
|
||||
Number of decay modes present
|
||||
|
||||
:decay_energy:
|
||||
Decay energy released in [eV]
|
||||
|
||||
:reactions:
|
||||
Number of reactions present
|
||||
|
||||
For each decay mode, a :ref:`io_chain_decay` appears as a child of
|
||||
``<nuclide>``. For each reaction present, a :ref:`io_chain_reaction` appears as
|
||||
a child of ``<nuclide>``. If the nuclide is fissionable, a :ref:`io_chain_nfy`
|
||||
appears as well.
|
||||
|
||||
.. _io_chain_decay:
|
||||
|
||||
-------------------
|
||||
``<decay>`` Element
|
||||
-------------------
|
||||
|
||||
The ``<decay>`` element represents a single decay mode and has the following
|
||||
attributes:
|
||||
|
||||
:type:
|
||||
The type of the decay, e.g. 'ec/beta+'
|
||||
|
||||
:target:
|
||||
The daughter nuclide produced from the decay
|
||||
|
||||
:branching_ratio:
|
||||
The branching ratio for this decay mode
|
||||
|
||||
.. _io_chain_reaction:
|
||||
|
||||
----------------------
|
||||
``<reaction>`` Element
|
||||
----------------------
|
||||
|
||||
The ``<reaction>`` element represents a single transmutation reaction. This
|
||||
element has the following attributes:
|
||||
|
||||
:type:
|
||||
The type of the reaction, e.g., '(n,gamma)'
|
||||
|
||||
:Q:
|
||||
The Q value of the reaction in [eV]
|
||||
|
||||
:target:
|
||||
The nuclide produced in the reaction (absent if the type is 'fission')
|
||||
|
||||
:branching_ratio:
|
||||
The branching ratio for the reaction
|
||||
|
||||
.. _io_chain_nfy:
|
||||
|
||||
------------------------------------
|
||||
``<neutron_fission_yields>`` Element
|
||||
------------------------------------
|
||||
|
||||
The ``<neutron_fission_yields>`` element provides yields of fission products for
|
||||
fissionable nuclides. It has the follow sub-elements:
|
||||
|
||||
:energies:
|
||||
Energies in [eV] at which yields for products are tabulated
|
||||
|
||||
:fission_yields:
|
||||
|
||||
Fission product yields for a single energy point. This element itself has a
|
||||
number of attributes/sub-elements:
|
||||
|
||||
:energy:
|
||||
Energy in [eV] at which yields are tabulated
|
||||
|
||||
:products:
|
||||
Names of fission products
|
||||
|
||||
:data:
|
||||
Independent yields for each fission product
|
||||
42
docs/source/io_formats/depletion_results.rst
Normal file
42
docs/source/io_formats/depletion_results.rst
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
.. _io_depletion_results:
|
||||
|
||||
=============================
|
||||
Depletion Results File Format
|
||||
=============================
|
||||
|
||||
The current version of the depletion results file format is 1.0.
|
||||
|
||||
**/**
|
||||
|
||||
:Attributes: - **filetype** (*char[]*) -- String indicating the type of file.
|
||||
- **version** (*int[2]*) -- Major and minor version of the
|
||||
statepoint file format.
|
||||
|
||||
:Datasets: - **eigenvalues** (*double[][]*) -- k-eigenvalues at each
|
||||
time/stage. This array has shape (number of timesteps, number of
|
||||
stages).
|
||||
- **number** (*double[][][][]*) -- Total number of atoms. This array
|
||||
has shape (number of timesteps, number of stages, number of
|
||||
materials, number of nuclides).
|
||||
- **reaction rates** (*double[][][][][]*) -- Reaction rates used to
|
||||
build depletion matrices. This array has shape (number of
|
||||
timesteps, number of stages, number of materials, number of
|
||||
nuclides, number of reactions).
|
||||
- **time** (*double[][2]*) -- Time in [s] at beginning/end of each
|
||||
step.
|
||||
|
||||
**/materials/<id>/**
|
||||
|
||||
:Attributes: - **index** (*int*) -- Index used in results for this material
|
||||
- **volume** (*double*) -- Volume of this material in [cm^3]
|
||||
|
||||
**/nuclides/<name>/**
|
||||
|
||||
:Attributes: - **atom number index** (*int*) -- Index in array of total atoms
|
||||
for this nuclide
|
||||
- **reaction rate index** (*int*) -- Index in array of reaction
|
||||
rates for this nuclide
|
||||
|
||||
**/reactions/<name>/**
|
||||
|
||||
:Attributes: - **index** (*int*) -- Index user in results for this reaction
|
||||
|
|
@ -12,7 +12,7 @@ Input Files
|
|||
|
||||
.. toctree::
|
||||
:numbered:
|
||||
:maxdepth: 2
|
||||
:maxdepth: 1
|
||||
|
||||
geometry
|
||||
materials
|
||||
|
|
@ -27,9 +27,10 @@ Data Files
|
|||
|
||||
.. toctree::
|
||||
:numbered:
|
||||
:maxdepth: 2
|
||||
:maxdepth: 1
|
||||
|
||||
cross_sections
|
||||
depletion_chain
|
||||
nuclear_data
|
||||
mgxs_library
|
||||
data_wmp
|
||||
|
|
@ -41,11 +42,12 @@ Output Files
|
|||
|
||||
.. toctree::
|
||||
:numbered:
|
||||
:maxdepth: 2
|
||||
:maxdepth: 1
|
||||
|
||||
statepoint
|
||||
source
|
||||
summary
|
||||
depletion_results
|
||||
particle_restart
|
||||
track
|
||||
voxel
|
||||
|
|
|
|||
|
|
@ -92,20 +92,8 @@ 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
|
||||
|
||||
.. note:: The ``scattering`` attribute/sub-element is not used in the
|
||||
multi-group :ref:`energy_mode`.
|
||||
|
||||
:sab:
|
||||
Associates an S(a,b) table with the material. This element has an
|
||||
attribute/sub-element called ``name``. The ``name`` attribute
|
||||
|
|
@ -119,6 +107,17 @@ Each ``material`` element can have the following attributes or sub-elements:
|
|||
|
||||
.. note:: This element is not used in the multi-group :ref:`energy_mode`.
|
||||
|
||||
:isotropic:
|
||||
The ``isotropic`` element indicates a list of nuclides for which elastic
|
||||
scattering should be treated as though it were isotropic in the laboratory
|
||||
system. This element 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*: No nuclides are treated as have isotropic elastic scattering.
|
||||
|
||||
.. note:: This element is not used in the multi-group :ref:`energy_mode`.
|
||||
|
||||
:macroscopic:
|
||||
The ``macroscopic`` element is similar to the ``nuclide`` element, but,
|
||||
recognizes that some multi-group libraries may be providing material
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
License Agreement
|
||||
=================
|
||||
|
||||
Copyright © 2011-2017 Massachusetts Institute of Technology
|
||||
Copyright © 2011-2018 Massachusetts Institute of Technology
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ dividing space into two half-spaces.
|
|||
|
||||
.. _fig-halfspace:
|
||||
|
||||
.. figure:: ../_images/halfspace.*
|
||||
.. figure:: ../_images/halfspace.svg
|
||||
:align: center
|
||||
:figclass: align-center
|
||||
|
||||
|
|
@ -63,7 +63,7 @@ defined as the intersection of an ellipse and two planes.
|
|||
|
||||
.. _fig-union:
|
||||
|
||||
.. figure:: ../_images/union.*
|
||||
.. figure:: ../_images/union.svg
|
||||
:align: center
|
||||
:figclass: align-center
|
||||
|
||||
|
|
@ -482,7 +482,7 @@ upper-right tiles, respectively.
|
|||
|
||||
.. _fig-rect-lat:
|
||||
|
||||
.. figure:: ../_images/rect_lat.*
|
||||
.. figure:: ../_images/rect_lat.svg
|
||||
:align: center
|
||||
:figclass: align-center
|
||||
:width: 400px
|
||||
|
|
@ -521,7 +521,7 @@ right side.
|
|||
|
||||
.. _fig-hex-lat:
|
||||
|
||||
.. figure:: ../_images/hex_lat.*
|
||||
.. figure:: ../_images/hex_lat.svg
|
||||
:align: center
|
||||
:figclass: align-center
|
||||
:width: 400px
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ Overviews
|
|||
|
||||
- Paul K. Romano, Nicholas E. Horelik, Bryan R. Herman, Adam G. Nelson, Benoit
|
||||
Forget, and Kord Smith, "`OpenMC: A State-of-the-Art Monte Carlo Code for
|
||||
Research and Development <http://dx.doi.org/10.1016/j.anucene.2014.07.048>`_,"
|
||||
Research and Development <https://doi.org/10.1016/j.anucene.2014.07.048>`_,"
|
||||
*Ann. Nucl. Energy*, **82**, 90--97 (2015).
|
||||
|
||||
- Paul K. Romano, Bryan R. Herman, Nicholas E. Horelik, Benoit Forget, Kord
|
||||
|
|
@ -19,16 +19,19 @@ Overviews
|
|||
Nuclear Science and Engineering*, Sun Valley, Idaho, May 5--9 (2013).
|
||||
|
||||
- Paul K. Romano and Benoit Forget, "`The OpenMC Monte Carlo Particle Transport
|
||||
Code <http://dx.doi.org/10.1016/j.anucene.2012.06.040>`_,"
|
||||
Code <https://doi.org/10.1016/j.anucene.2012.06.040>`_,"
|
||||
*Ann. Nucl. Energy*, **51**, 274--281 (2013).
|
||||
|
||||
------------
|
||||
Benchmarking
|
||||
------------
|
||||
|
||||
- Travis J. Labossiere-Hickman and Benoit Forget, "Selected VERA Core Physics
|
||||
Benchmarks in OpenMC," *Trans. Am. Nucl. Soc.*, **117**, 1520-1523 (2017).
|
||||
|
||||
- Khurrum S. Chaudri and Sikander M. Mirza, "`Burnup dependent Monte Carlo
|
||||
neutron physics calculations of IAEA MTR benchmark
|
||||
<http://dx.doi.org/10.1016/j.pnucene.2014.12.018>`_," *Prog. Nucl. Energy*,
|
||||
<https://doi.org/10.1016/j.pnucene.2014.12.018>`_," *Prog. Nucl. Energy*,
|
||||
**81**, 43-52 (2015).
|
||||
|
||||
- Daniel J. Kelly, Brian N. Aviles, Paul K. Romano, Bryan R. Herman,
|
||||
|
|
@ -54,10 +57,15 @@ Benchmarking
|
|||
Coupling and Multi-physics
|
||||
--------------------------
|
||||
|
||||
- Tianliang Hu, Liangzhu Cao, Hongchun Wu, Xianan Du, and Mingtao He, "`Coupled
|
||||
neutrons and thermal-hydraulics simulation of molten salt reactors based on
|
||||
OpenMC/TANSY <https://doi.org/10.1016/j.anucene.2017.05.002>`_,"
|
||||
*Ann. Nucl. Energy*, **109**, 260-276 (2017).
|
||||
|
||||
- Matthew Ellis, Derek Gaston, Benoit Forget, and Kord Smith, "`Preliminary
|
||||
Coupling of the Monte Carlo Code OpenMC and the Multiphysics Object-Oriented
|
||||
Simulation Environment for Analyzing Doppler Feedback in Monte Carlo
|
||||
Simulations <http://dx.doi.org/10.13182/NSE16-26>`_," *Nucl. Sci. Eng.*,
|
||||
Simulations <https://doi.org/10.13182/NSE16-26>`_," *Nucl. Sci. Eng.*,
|
||||
**185**, 184-193 (2017).
|
||||
|
||||
- Matthew Ellis, Benoit Forget, Kord Smith, and Derek Gaston, "Continuous
|
||||
|
|
@ -79,7 +87,7 @@ 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 <http://dx.doi.org/10.1016/j.anucene.2014.10.029>`_,"
|
||||
acceleration methods <https://doi.org/10.1016/j.anucene.2014.10.029>`_,"
|
||||
*Ann. Nucl. Energy*, **84**, 63-72 (2015).
|
||||
|
||||
- Bryan R. Herman, Benoit Forget, and Kord Smith, "Utilizing CMFD in OpenMC to
|
||||
|
|
@ -106,6 +114,15 @@ Geometry and Visualization
|
|||
Miscellaneous
|
||||
-------------
|
||||
|
||||
- Adam G. Nelson, Samuel Shaner, William Boyd, and Paul K. Romano,
|
||||
"Incorporation of a Multigroup Transport Capability in the OpenMC Monte Carlo
|
||||
Particle Transport Code," *Trans. Am. Nucl. Soc.*, **117**, 679-681 (2017).
|
||||
|
||||
- Youqi Zheng, Yunlong Xiao, and Hongchun Wu, "`Application of the virtual
|
||||
density theory in fast reactor analysis based on the neutron transport
|
||||
calculation <https://doi.org/10.1016/j.nucengdes.2017.05.020>`_,"
|
||||
*Nucl. Eng. Des.*, **320**, 200-206 (2017).
|
||||
|
||||
- Amanda L. Lund, Paul K. Romano, and Andrew R. Siegel, "Accelerating Source
|
||||
Convergence in Monte Carlo Criticality Calculations Using a Particle Ramp-Up
|
||||
Technique," *Proc. Int. Conf. Mathematics & Computational Methods Applied to
|
||||
|
|
@ -126,7 +143,7 @@ Miscellaneous
|
|||
|
||||
- Yunzhao Li, Qingming He, Liangzhi Cao, Hongchun Wu, and Tiejun Zu, "`Resonance
|
||||
Elastic Scattering and Interference Effects Treatments in Subgroup Method
|
||||
<http://dx.doi.org/10.1016/j.net.2015.12.015>`_," *Nucl. Eng. Tech.*, **48**,
|
||||
<https://doi.org/10.1016/j.net.2015.12.015>`_," *Nucl. Eng. Tech.*, **48**,
|
||||
339-350 (2016).
|
||||
|
||||
- William Boyd, Sterling Harper, and Paul K. Romano, "Equipping OpenMC for the
|
||||
|
|
@ -135,7 +152,7 @@ Miscellaneous
|
|||
- Michal Kostal, Vojtech Rypar, Jan Milcak, Vlastimil Juricek, Evzen Losa,
|
||||
Benoit Forget, and Sterling Harper, "`Study of graphite reactivity worth on
|
||||
well-defined cores assembled on LR-0 reactor
|
||||
<http://dx.doi.org/10.1016/j.anucene.2015.10.010>`_," *Ann. Nucl. Energy*,
|
||||
<https://doi.org/10.1016/j.anucene.2015.10.010>`_," *Ann. Nucl. Energy*,
|
||||
**87**, 601-611 (2016).
|
||||
|
||||
- Qicang Shen, William Boyd, Benoit Forget, and Kord Smith, "Tally precision
|
||||
|
|
@ -154,9 +171,25 @@ Miscellaneous
|
|||
Multi-group Cross Section Generation
|
||||
------------------------------------
|
||||
|
||||
- Zhaoyuan Liu, Kord Smith, Benoit Forget, and Javier Ortensi, "`Cumulative
|
||||
migration method for computing rigorous diffusion coefficients and transport
|
||||
cross sections from Monte Carlo
|
||||
<https://doi.org/10.1016/j.anucene.2017.10.039>`_," *Ann. Nucl. Energy*,
|
||||
**112**, 507-516 (2018).
|
||||
|
||||
- Gang Yang, Tongkyu Park, and Won Sik Yang, "Effects of Fuel Salt Velocity
|
||||
Field on Neutronics Performances in Molten Salt Reactors with Open Flow
|
||||
Channels," *Trans. Am. Nucl. Soc.*, **117**, 1339-1342 (2017).
|
||||
|
||||
- William Boyd, Nathan Gibson, Benoit Forget, and Kord Smith, "`An analysis of
|
||||
condensation errors in multi-group cross section generation for fine-mesh
|
||||
neutron transport calculations
|
||||
<https://doi.org/10.1016/j.anucene.2017.09.052>`_," *Ann. Nucl. Energy*,
|
||||
**112**, 267-276 (2018).
|
||||
|
||||
- Hong Shuang, Yang Yongwei, Zhang Lu, and Gao Yucui, "`Fabrication and
|
||||
validation of multigroup cross section library based on the OpenMC code
|
||||
<http://dx.doi.org/10.11889/j.0253-3219.2017.hjs.40.040502>`_,"
|
||||
<https://doi.org/10.11889/j.0253-3219.2017.hjs.40.040502>`_,"
|
||||
*Nucl. Techniques* **40** (4), 040504 (2017). (in Mandarin)
|
||||
|
||||
- Nicholas E. Stauff, Changho Lee, Paul K. Romano, and Taek K. Kim,
|
||||
|
|
@ -207,7 +240,7 @@ Doppler Broadening
|
|||
|
||||
- Colin Josey, Pablo Ducru, Benoit Forget, and Kord Smith, "`Windowed multipole
|
||||
for cross section Doppler broadening
|
||||
<http://dx.doi.org/10.1016/j.jcp.2015.08.013>`_," *J. Comput. Phys.*, **307**,
|
||||
<https://doi.org/10.1016/j.jcp.2015.08.013>`_," *J. Comput. Phys.*, **307**,
|
||||
715-727 (2016).
|
||||
|
||||
- Jonathan A. Walsh, Benoit Forget, Kord S. Smith, and Forrest B. Brown,
|
||||
|
|
@ -217,12 +250,12 @@ Doppler Broadening
|
|||
|
||||
- Colin Josey, Benoit Forget, and Kord Smith, "`Windowed multipole sensitivity
|
||||
to target accuracy of the optimization procedure
|
||||
<http://dx.doi.org/10.1080/00223131.2015.1035353>`_,"
|
||||
<https://doi.org/10.1080/00223131.2015.1035353>`_,"
|
||||
*J. Nucl. Sci. Technol.*, **52**, 987-992 (2015).
|
||||
|
||||
- Paul K. Romano and Timothy H. Trumbull, "`Comparison of algorithms for Doppler
|
||||
broadening pointwise tabulated cross sections
|
||||
<http://dx.doi.org/10.1016/j.anucene.2014.08.046>`_," *Ann. Nucl. Energy*,
|
||||
<https://doi.org/10.1016/j.anucene.2014.08.046>`_," *Ann. Nucl. Energy*,
|
||||
**75**, 358--364 (2015).
|
||||
|
||||
- Tuomas Viitanen, Jaakko Leppanen, and Benoit Forget, "Target motion sampling
|
||||
|
|
@ -231,13 +264,17 @@ Doppler Broadening
|
|||
|
||||
- Benoit Forget, Sheng Xu, and Kord Smith, "`Direct Doppler broadening in Monte
|
||||
Carlo simulations using the multipole representation
|
||||
<http://dx.doi.org/10.1016/j.anucene.2013.09.043>`_," *Ann. Nucl. Energy*,
|
||||
<https://doi.org/10.1016/j.anucene.2013.09.043>`_," *Ann. Nucl. Energy*,
|
||||
**64**, 78--85 (2014).
|
||||
|
||||
------------
|
||||
Nuclear Data
|
||||
------------
|
||||
|
||||
- Jonathan A. Walsh, "Comparison of Unresolved Resonance Region Cross Section
|
||||
Formalisms in Transport Simulations," *Trans. Am. Nucl. Soc.*, **117**,
|
||||
749-752 (2017).
|
||||
|
||||
- Jonathan A. Walsh, Benoit Forget, Kord S. Smith, and Forrest B. Brown,
|
||||
"`Uncertainty in Fast Reactor-Relevant Critical Benchmark Simulations Due to
|
||||
Unresolved Resonance Structure
|
||||
|
|
@ -255,13 +292,13 @@ Nuclear Data
|
|||
- Jonathan A. Walsh, Benoit Froget, Kord S. Smith, and Forrest B. Brown,
|
||||
"`Neutron Cross Section Processing Methods for Improved Integral Benchmarking
|
||||
of Unresolved Resonance Region Evaluations
|
||||
<http://dx.doi.org/10.1051/epjconf/201611106001>`_," *Eur. Phys. J. Web Conf.*
|
||||
<https://doi.org/10.1051/epjconf/201611106001>`_," *Eur. Phys. J. Web Conf.*
|
||||
**111**, 06001 (2016).
|
||||
|
||||
- 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
|
||||
<http://dx.doi.org/10.1016/j.cpc.2015.05.025>`_", *Comput. Phys. Commun.*,
|
||||
<https://doi.org/10.1016/j.cpc.2015.05.025>`_", *Comput. Phys. Commun.*,
|
||||
**196**, 134-142 (2015).
|
||||
|
||||
- Jonathan A. Walsh, Benoit Forget, Kord S. Smith, Brian C. Kiedrowski, and
|
||||
|
|
@ -280,7 +317,7 @@ Nuclear Data
|
|||
|
||||
- Jonathan A. Walsh, Benoit Forget, and Kord S. Smith, "`Accelerated sampling of
|
||||
the free gas resonance elastic scattering kernel
|
||||
<http://dx.doi.org/10.1016/j.anucene.2014.01.017>`_," *Ann. Nucl. Energy*,
|
||||
<https://doi.org/10.1016/j.anucene.2014.01.017>`_," *Ann. Nucl. Energy*,
|
||||
**69**, 116--124 (2014).
|
||||
|
||||
-----------
|
||||
|
|
@ -325,45 +362,45 @@ Parallelism
|
|||
|
||||
- Nicholas Horelik, Andrew Siegel, Benoit Forget, and Kord Smith, "`Monte Carlo
|
||||
domain decomposition for robust nuclear reactor analysis
|
||||
<http://dx.doi.org/10.1016/j.parco.2014.10.001>`_," *Parallel Comput.*,
|
||||
<https://doi.org/10.1016/j.parco.2014.10.001>`_," *Parallel Comput.*,
|
||||
**40**, 646--660 (2014).
|
||||
|
||||
- Andrew Siegel, Kord Smith, Kyle Felker, Paul Romano, Benoit Forget, and Peter
|
||||
Beckman, "`Improved cache performance in Monte Carlo transport calculations
|
||||
using energy banding <http://dx.doi.org/10.1016/j.cpc.2013.10.008>`_,"
|
||||
using energy banding <https://doi.org/10.1016/j.cpc.2013.10.008>`_,"
|
||||
*Comput. Phys. Commun.*, **185** (4), 1195--1199 (2014).
|
||||
|
||||
- Paul K. Romano, Benoit Forget, Kord Smith, and Andrew Siegel, "`On the use of
|
||||
tally servers in Monte Carlo simulations of light-water reactors
|
||||
<http://dx.doi.org/10.1051/snamc/201404301>`_," *Proc. Joint International
|
||||
<https://doi.org/10.1051/snamc/201404301>`_," *Proc. Joint International
|
||||
Conference on Supercomputing in Nuclear Applications and Monte Carlo*, Paris,
|
||||
France, Oct. 27--31 (2013).
|
||||
|
||||
- Kyle G. Felker, Andrew R. Siegel, Kord S. Smith, Paul K. Romano, and Benoit
|
||||
Forget, "`The energy band memory server algorithm for parallel Monte Carlo
|
||||
calculations <http://dx.doi.org/10.1051/snamc/201404207>`_," *Proc. Joint
|
||||
calculations <https://doi.org/10.1051/snamc/201404207>`_," *Proc. Joint
|
||||
International Conference on Supercomputing in Nuclear Applications and Monte
|
||||
Carlo*, Paris, France, Oct. 27--31 (2013).
|
||||
|
||||
- John R. Tramm and Andrew R. Siegel, "`Memory Bottlenecks and Memory Contention
|
||||
in Multi-Core Monte Carlo Transport Codes
|
||||
<http://dx.doi.org/10.1051/snamc/201404208>`_," *Proc. Joint International
|
||||
<https://doi.org/10.1051/snamc/201404208>`_," *Proc. Joint International
|
||||
Conference on Supercomputing in Nuclear Applications and Monte Carlo*, Paris,
|
||||
France, Oct. 27--31 (2013).
|
||||
|
||||
- Andrew R. Siegel, Kord Smith, Paul K. Romano, Benoit Forget, and Kyle Felker,
|
||||
"`Multi-core performance studies of a Monte Carlo neutron transport code
|
||||
<http://dx.doi.org/10.1177/1094342013492179>`_," *Int. J. High
|
||||
<https://doi.org/10.1177/1094342013492179>`_," *Int. J. High
|
||||
Perform. Comput. Appl.*, **28** (1), 87--96 (2014).
|
||||
|
||||
- Paul K. Romano, Andrew R. Siegel, Benoit Forget, and Kord Smith, "`Data
|
||||
decomposition of Monte Carlo particle transport simulations via tally servers
|
||||
<http://dx.doi.org/10.1016/j.jcp.2013.06.011>`_," *J. Comput. Phys.*, **252**,
|
||||
<https://doi.org/10.1016/j.jcp.2013.06.011>`_," *J. Comput. Phys.*, **252**,
|
||||
20--36 (2013).
|
||||
|
||||
- Andrew R. Siegel, Kord Smith, Paul K. Romano, Benoit Forget, and Kyle Felker,
|
||||
"`The effect of load imbalances on the performance of Monte Carlo codes in LWR
|
||||
analysis <http://dx.doi.org/10.1016/j.jcp.2012.06.012>`_," *J. Comput. Phys.*,
|
||||
analysis <https://doi.org/10.1016/j.jcp.2012.06.012>`_," *J. Comput. Phys.*,
|
||||
**235**, 901--911 (2013).
|
||||
|
||||
|
||||
|
|
@ -372,13 +409,18 @@ Parallelism
|
|||
519--522 (2012).
|
||||
|
||||
- Paul K. Romano and Benoit Forget, "`Parallel Fission Bank Algorithms in Monte
|
||||
Carlo Criticality Calculations <http://dx.doi.org/10.13182/NSE10-98>`_,"
|
||||
Carlo Criticality Calculations <https://doi.org/10.13182/NSE10-98>`_,"
|
||||
*Nucl. Sci. Eng.*, **170**, 125--135 (2012).
|
||||
|
||||
---------
|
||||
Depletion
|
||||
---------
|
||||
|
||||
- Colin Josey, Benoit Forget, and Kord Smith, "`High order methods for the
|
||||
integration of the Bateman equations and other problems of the form of y' =
|
||||
F(y,t)y <https://doi.org/10.1016/j.jcp.2017.08.025>`_," *J. Comput. Phys.*,
|
||||
**350**, 296-313 (2017).
|
||||
|
||||
- Matthew S. Ellis, Colin Josey, Benoit Forget, and Kord Smith, "`Spatially
|
||||
Continuous Depletion Algorithm for Monte Carlo Simulations
|
||||
<http://hdl.handle.net/1721.1/107880>`_," *Trans. Am. Nucl. Soc.*, **115**,
|
||||
|
|
@ -386,7 +428,7 @@ Depletion
|
|||
|
||||
- Anas Gul, K. S. Chaudri, R. Khan, and M. Azeen, "`Development and verification
|
||||
of LOOP: A Linkage of ORIGEN2.2 and OpenMC
|
||||
<http://dx.doi.org/10.1016/j.anucene.2016.09.016>`_," *Ann. Nucl. Energy*,
|
||||
<https://doi.org/10.1016/j.anucene.2016.09.016>`_," *Ann. Nucl. Energy*,
|
||||
**99**, 321--327 (2017).
|
||||
|
||||
- Kai Huang, Hongchun Wu, Yunzhao Li, and Liangzhi Cao, "Generalized depletion
|
||||
|
|
|
|||
|
|
@ -91,18 +91,6 @@ Many of the above classes are derived from several abstract classes:
|
|||
openmc.Region
|
||||
openmc.Lattice
|
||||
|
||||
Two helper function are also available to create rectangular and hexagonal
|
||||
prisms defined by the intersection of four and six surface half-spaces,
|
||||
respectively.
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated
|
||||
:nosignatures:
|
||||
:template: myfunction.rst
|
||||
|
||||
openmc.get_hexagonal_prism
|
||||
openmc.get_rectangular_prism
|
||||
|
||||
.. _pythonapi_tallies:
|
||||
|
||||
Constructing Tallies
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
---------------------------------------------------
|
||||
:data:`openmc.capi` -- Python bindings to the C API
|
||||
---------------------------------------------------
|
||||
--------------------------------------------------
|
||||
:mod:`openmc.capi` -- Python bindings to the C API
|
||||
--------------------------------------------------
|
||||
|
||||
.. automodule:: openmc.capi
|
||||
|
||||
|
|
@ -12,18 +12,25 @@ Functions
|
|||
:nosignatures:
|
||||
:template: myfunction.rst
|
||||
|
||||
openmc.capi.calculate_volumes
|
||||
openmc.capi.finalize
|
||||
openmc.capi.find_cell
|
||||
openmc.capi.find_material
|
||||
openmc.capi.hard_reset
|
||||
openmc.capi.init
|
||||
openmc.capi.keff
|
||||
openmc.capi.load_nuclide
|
||||
openmc.capi.plot_geometry
|
||||
openmc.capi.reset
|
||||
openmc.capi.run
|
||||
openmc.capi.run_in_memory
|
||||
calculate_volumes
|
||||
finalize
|
||||
find_cell
|
||||
find_material
|
||||
hard_reset
|
||||
init
|
||||
iter_batches
|
||||
keff
|
||||
load_nuclide
|
||||
next_batch
|
||||
num_realizations
|
||||
plot_geometry
|
||||
reset
|
||||
run
|
||||
run_in_memory
|
||||
simulation_init
|
||||
simulation_finalize
|
||||
source_bank
|
||||
statepoint_write
|
||||
|
||||
Classes
|
||||
-------
|
||||
|
|
@ -33,9 +40,9 @@ Classes
|
|||
:nosignatures:
|
||||
:template: myclass.rst
|
||||
|
||||
openmc.capi.Cell
|
||||
openmc.capi.EnergyFilter
|
||||
openmc.capi.MaterialFilter
|
||||
openmc.capi.Material
|
||||
openmc.capi.Nuclide
|
||||
openmc.capi.Tally
|
||||
Cell
|
||||
EnergyFilter
|
||||
MaterialFilter
|
||||
Material
|
||||
Nuclide
|
||||
Tally
|
||||
|
|
|
|||
|
|
@ -35,9 +35,12 @@ Core Functions
|
|||
:template: myfunction.rst
|
||||
|
||||
openmc.data.atomic_mass
|
||||
openmc.data.gnd_name
|
||||
openmc.data.linearize
|
||||
openmc.data.thin
|
||||
openmc.data.water_density
|
||||
openmc.data.write_compact_458_library
|
||||
openmc.data.zam
|
||||
|
||||
Angle-Energy Distributions
|
||||
--------------------------
|
||||
|
|
|
|||
85
docs/source/pythonapi/deplete.rst
Normal file
85
docs/source/pythonapi/deplete.rst
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
.. _pythonapi_deplete:
|
||||
|
||||
----------------------------------
|
||||
:mod:`openmc.deplete` -- Depletion
|
||||
----------------------------------
|
||||
|
||||
.. module:: openmc.deplete
|
||||
|
||||
Two functions are provided that implement different time-integration algorithms
|
||||
for depletion calculations.
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated
|
||||
:nosignatures:
|
||||
:template: myfunction.rst
|
||||
|
||||
integrator.predictor
|
||||
integrator.cecm
|
||||
|
||||
Each of these functions expects a "transport operator" to be passed. An operator
|
||||
specific to OpenMC is available using the following class:
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated
|
||||
:nosignatures:
|
||||
:template: myclass.rst
|
||||
|
||||
Operator
|
||||
|
||||
When running in parallel using `mpi4py <http://mpi4py.scipy.org>`_, the MPI
|
||||
intercommunicator used can be changed by modifying the following module
|
||||
variable. If it is not explicitly modified, it defaults to
|
||||
``mpi4py.MPI.COMM_WORLD``.
|
||||
|
||||
.. data:: comm
|
||||
|
||||
MPI intercommunicator used to call OpenMC library
|
||||
|
||||
:type: mpi4py.MPI.Comm
|
||||
|
||||
Internal Classes and Functions
|
||||
------------------------------
|
||||
|
||||
During a depletion calculation, the depletion chain, reaction rates, and number
|
||||
densities are managed through a series of internal classes that are not normally
|
||||
visible to a user. However, should you find yourself wondering about these
|
||||
classes (e.g., if you want to know what decay modes or reactions are present in
|
||||
a depletion chain), they are documented here. The following classes store data
|
||||
for a depletion chain:
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated
|
||||
:nosignatures:
|
||||
:template: myclass.rst
|
||||
|
||||
Chain
|
||||
DecayTuple
|
||||
Nuclide
|
||||
ReactionTuple
|
||||
|
||||
The following classes are used during a depletion simulation and store auxiliary
|
||||
data, such as number densities and reaction rates for each material.
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated
|
||||
:nosignatures:
|
||||
:template: myclass.rst
|
||||
|
||||
AtomNumber
|
||||
OperatorResult
|
||||
ReactionRates
|
||||
Results
|
||||
ResultsList
|
||||
TransportOperator
|
||||
|
||||
Each of the integrator functions also relies on a number of "helper" functions
|
||||
as follows:
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated
|
||||
:nosignatures:
|
||||
:template: myfunction.rst
|
||||
|
||||
integrator.CRAM16
|
||||
integrator.CRAM48
|
||||
|
|
@ -15,14 +15,15 @@ there are many substantial benefits to using the Python API, including:
|
|||
- The ability to define dimensions using variables.
|
||||
- Availability of standard-library modules for working with files.
|
||||
- An entire ecosystem of third-party packages for scientific computing.
|
||||
- Ability to create materials based on natural elements or uranium enrichment
|
||||
- Automated multi-group cross section generation (:mod:`openmc.mgxs`)
|
||||
- A fully-featured nuclear data interface (:mod:`openmc.data`)
|
||||
- Depletion capability (:mod:`openmc.deplete`)
|
||||
- Convenience functions (e.g., a function returning a hexagonal region)
|
||||
- Ability to plot individual universes as geometry is being created
|
||||
- A :math:`k_\text{eff}` search function (:func:`openmc.search_for_keff`)
|
||||
- Random sphere packing for generating TRISO particle locations
|
||||
(:func:`openmc.model.pack_trisos`)
|
||||
- A fully-featured nuclear data interface (:mod:`openmc.data`)
|
||||
- Ability to create materials based on natural elements or uranium enrichment
|
||||
|
||||
For those new to Python, there are many good tutorials available online. We
|
||||
recommend going through the modules from `Codecademy
|
||||
|
|
@ -40,13 +41,14 @@ Modules
|
|||
-------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:maxdepth: 1
|
||||
|
||||
base
|
||||
stats
|
||||
mgxs
|
||||
model
|
||||
examples
|
||||
deplete
|
||||
mgxs
|
||||
stats
|
||||
data
|
||||
capi
|
||||
examples
|
||||
openmoc
|
||||
|
|
|
|||
|
|
@ -2,6 +2,19 @@
|
|||
:mod:`openmc.model` -- Model Building
|
||||
-------------------------------------
|
||||
|
||||
Convenience Functions
|
||||
---------------------
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated
|
||||
:nosignatures:
|
||||
:template: myfunction.rst
|
||||
|
||||
openmc.model.borated_water
|
||||
openmc.model.get_hexagonal_prism
|
||||
openmc.model.get_rectangular_prism
|
||||
openmc.model.subdivide
|
||||
|
||||
TRISO Fuel Modeling
|
||||
-------------------
|
||||
|
||||
|
|
|
|||
|
|
@ -44,20 +44,19 @@ Next, resynchronize the package index files:
|
|||
|
||||
.. code-block:: sh
|
||||
|
||||
sudo apt-get update
|
||||
sudo apt update
|
||||
|
||||
Now OpenMC should be recognized within the repository and can be installed:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
sudo apt-get install openmc
|
||||
sudo apt install openmc
|
||||
|
||||
Binary packages from this PPA may exist for earlier versions of Ubuntu, but they
|
||||
are no longer supported.
|
||||
|
||||
.. _Personal Package Archive: https://launchpad.net/~paulromano/+archive/staging
|
||||
.. _APT package manager: https://help.ubuntu.com/community/AptGet/Howto
|
||||
.. _HDF5: http://www.hdfgroup.org/HDF5/
|
||||
|
||||
---------------------------------------
|
||||
Installing from Source on Ubuntu 15.04+
|
||||
|
|
@ -69,9 +68,7 @@ installed directly from the package manager.
|
|||
|
||||
.. code-block:: sh
|
||||
|
||||
sudo apt-get install gfortran
|
||||
sudo apt-get install cmake
|
||||
sudo apt-get install libhdf5-dev
|
||||
sudo apt install gfortran g++ cmake libhdf5-dev
|
||||
|
||||
After the packages have been installed, follow the instructions below for
|
||||
building and installing OpenMC from source.
|
||||
|
|
@ -85,9 +82,12 @@ building and installing OpenMC from source.
|
|||
Installing from Source on Linux or Mac OS X
|
||||
-------------------------------------------
|
||||
|
||||
All OpenMC source code is hosted on GitHub_. If you have git_, the gfortran_
|
||||
compiler, CMake_, and HDF5_ installed, you can download and install OpenMC be
|
||||
entering the following commands in a terminal:
|
||||
All OpenMC source code is hosted on `GitHub
|
||||
<https://github.com/mit-crpg/openmc>`_. If you have `git
|
||||
<https://git-scm.com>`_, the `gcc <https://gcc.gnu.org/>`_ compiler suite,
|
||||
`CMake <http://www.cmake.org>`_, and `HDF5 <https://www.hdfgroup.org/HDF5/>`_
|
||||
installed, you can download and install OpenMC be entering the following
|
||||
commands in a terminal:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
|
|
@ -106,11 +106,15 @@ should specify an installation directory where you have write access, e.g.
|
|||
|
||||
cmake -DCMAKE_INSTALL_PREFIX=$HOME/.local ..
|
||||
|
||||
The :mod:`openmc` Python package must be installed separately. The easiest way
|
||||
to install it is using `pip <https://pip.pypa.io/en/stable/>`_, which is
|
||||
included by default in Python 2.7 and Python 3.4+. From the root directory of
|
||||
the OpenMC distribution/repository, run:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
pip install .
|
||||
|
||||
If you want to build a parallel version of OpenMC (using OpenMP or MPI),
|
||||
directions can be found in the :ref:`detailed installation instructions
|
||||
<usersguide_build>`.
|
||||
|
||||
.. _GitHub: https://github.com/mit-crpg/openmc
|
||||
.. _git: http://git-scm.com
|
||||
.. _gfortran: http://gcc.gnu.org/wiki/GFortran
|
||||
.. _CMake: http://www.cmake.org
|
||||
|
|
|
|||
|
|
@ -1,59 +1,41 @@
|
|||
.. _releasenotes:
|
||||
|
||||
==============================
|
||||
Release Notes for OpenMC 0.9.0
|
||||
==============================
|
||||
===============================
|
||||
Release Notes for OpenMC 0.10.0
|
||||
===============================
|
||||
|
||||
.. currentmodule:: openmc
|
||||
|
||||
This release of OpenMC is the first release to use a new native HDF5 cross
|
||||
section format rather than ACE format cross sections. Other significant new
|
||||
features include a nuclear data interface in the Python API (:mod:`openmc.data`)
|
||||
a stochastic volume calculation capability, a random sphere packing algorithm
|
||||
that can handle packing fractions up to 60%, and a new XML parser with
|
||||
significantly better performance than the parser used previously.
|
||||
|
||||
.. caution:: With the new cross section format, the default energy units are now
|
||||
**electronvolts (eV)** rather than megaelectronvolts (MeV)! If you
|
||||
are specifying an energy filter for a tally, make sure you use
|
||||
units of eV now.
|
||||
This release of OpenMC includes several new features, performance improvements,
|
||||
and bug fixes compared to version 0.9.0. Notably, a C API has been added that
|
||||
enables in-memory coupling of neutronics to other physics fields, e.g., burnup
|
||||
calculations and thermal-hydraulics. The C API is also backed by Python bindings
|
||||
in a new :mod:`openmc.capi` package. Users should be forewarned that the C API
|
||||
is still in an experimental state and the interface is likely to undergo changes
|
||||
in future versions.
|
||||
|
||||
The Python API continues to improve over time; several backwards incompatible
|
||||
changes were made in the API which users of previous versions should take note
|
||||
of:
|
||||
|
||||
- Each type of tally filter is now specified with a separate class. For example::
|
||||
- To indicate that nuclides in a material should be treated such that elastic
|
||||
scattering is isotropic in the laboratory system, there is a new
|
||||
:attr:`Material.isotropic` property::
|
||||
|
||||
energy_filter = openmc.EnergyFilter([0.0, 0.625, 4.0, 1.0e6, 20.0e6])
|
||||
mat = openmc.Material()
|
||||
mat.add_nuclide('H1', 1.0)
|
||||
mat.isotropic = ['H1']
|
||||
|
||||
- Several attributes of the :class:`Plot` class have changed (``color`` ->
|
||||
``color_by`` and ``col_spec`` > ``colors``). :attr:`Plot.colors` now accepts a
|
||||
dictionary mapping :class:`Cell` or :class:`Material` instances to RGB
|
||||
3-tuples or string colors names, e.g.::
|
||||
To treat all nuclides in a material this way, the
|
||||
:meth:`Material.make_isotropic_in_lab` method can still be used.
|
||||
|
||||
plot.colors = {
|
||||
fuel: 'yellow',
|
||||
water: 'blue'
|
||||
}
|
||||
- The initializers for :class:`openmc.Intersection` and :class:`openmc.Union`
|
||||
now expect an iterable.
|
||||
|
||||
- ``make_hexagon_region`` is now :func:`get_hexagonal_prism`
|
||||
- Several changes in :class:`Settings` attributes:
|
||||
- Auto-generated unique IDs for classes now start from 1 rather than 10000.
|
||||
|
||||
- ``weight`` is now set as ``Settings.cutoff['weight']``
|
||||
- Shannon entropy is now specified by passing a :class:`openmc.Mesh` to
|
||||
:attr:`Settings.entropy_mesh`
|
||||
- Uniform fission site method is now specified by passing a
|
||||
:class:`openmc.Mesh` to :attr:`Settings.ufs_mesh`
|
||||
- All ``sourcepoint_*`` options are now specified in a
|
||||
:attr:`Settings.sourcepoint` dictionary
|
||||
- Resonance scattering method is now specified as a dictionary in
|
||||
:attr:`Settings.resonance_scattering`
|
||||
- Multipole is now turned on by setting ``Settings.temperature['multipole'] =
|
||||
True``
|
||||
- The ``output_path`` attribute is now ``Settings.output['path']``
|
||||
|
||||
- All the ``openmc.mgxs.Nu*`` classes are gone. Instead, a ``nu`` argument was
|
||||
added to the constructor of the corresponding classes.
|
||||
.. attention:: This is the last release of OpenMC that will support Python
|
||||
2.7. Future releases of OpenMC will require Python 3.4 or later.
|
||||
|
||||
-------------------
|
||||
System Requirements
|
||||
|
|
@ -69,69 +51,34 @@ problem at hand (mostly on the number of nuclides and tallies in the problem).
|
|||
New Features
|
||||
------------
|
||||
|
||||
- Stochastic volume calculations
|
||||
- Multi-delayed group cross section generation
|
||||
- Ability to calculate multi-group cross sections over meshes
|
||||
- Temperature interpolation on cross section data
|
||||
- Nuclear data interface in Python API, :mod:`openmc.data`
|
||||
- Allow cutoff energy via :attr:`Settings.cutoff`
|
||||
- Ability to define fuel by enrichment (see :meth:`Material.add_element`)
|
||||
- Random sphere packing for TRISO particle generation,
|
||||
:func:`openmc.model.pack_trisos`
|
||||
- Critical eigenvalue search, :func:`openmc.search_for_keff`
|
||||
- Model container, :class:`openmc.model.Model`
|
||||
- In-line plotting in Jupyter, :func:`openmc.plot_inline`
|
||||
- Energy function tally filters, :class:`openmc.EnergyFunctionFilter`
|
||||
- Replaced FoX XML parser with `pugixml <http://pugixml.org/>`_
|
||||
- Cell/material instance counting, :meth:`Geometry.determine_paths`
|
||||
- Differential tallies (see :class:`openmc.TallyDerivative`)
|
||||
- Consistent multi-group scattering matrices
|
||||
- Improved documentation and new Jupyter notebooks
|
||||
- OpenMOC compatibility module, :mod:`openmc.openmoc_compatible`
|
||||
- Rotationally-periodic boundary conditions
|
||||
- C API (with Python bindings) for in-memory coupling
|
||||
- Improved correlation for Uranium enrichment
|
||||
- Support for partial S(a,b) tables
|
||||
- Improved handling of autogenerated IDs
|
||||
- Many performance/memory improvements
|
||||
|
||||
---------
|
||||
Bug Fixes
|
||||
---------
|
||||
|
||||
- c5df6c_: Fix mesh filter max iterator check
|
||||
- 1cfa39_: Reject external source only if 95% of sites are rejected
|
||||
- 335359_: Fix bug in plotting meshlines
|
||||
- 17c678_: Make sure system_clock uses high-resolution timer
|
||||
- 23ec0b_: Fix use of S(a,b) with multipole data
|
||||
- 7eefb7_: Fix several bugs in tally module
|
||||
- 7880d4_: Allow plotting calculation with no boundary conditions
|
||||
- ad2d9f_: Fix filter weight missing when scoring all nuclides
|
||||
- 59fdca_: Fix use of source files for fixed source calculations
|
||||
- 9eff5b_: Fix thermal scattering bugs
|
||||
- 7848a9_: Fix combined k-eff estimator producing NaN
|
||||
- f139ce_: Fix printing bug for tallies with AggregateNuclide
|
||||
- b8ddfa_: Bugfix for short tracks near tally mesh edges
|
||||
- ec3cfb_: Fix inconsistency in filter weights
|
||||
- 5e9b06_: Fix XML representation for verbosity
|
||||
- c39990_: Fix bug tallying reaction rates with multipole on
|
||||
- c6b67e_: Fix fissionable source sampling bug
|
||||
- 489540_: Check for void materials in tracklength tallies
|
||||
- f0214f_: Fixes/improvements to the ARES algorithm
|
||||
- 937469_: Fix energy group sampling for multi-group simulations
|
||||
- a149ef_: Ensure mutable objects are not hashable
|
||||
- 2c9b21_: Preserve backwards compatibility for generated HDF5 libraries
|
||||
- 8047f6_: Handle units of division for tally arithmetic correctly
|
||||
- 0beb4c_: Compatibility with newer versions of Pandas
|
||||
- f124be_: Fix generating 0K data with openmc.data.njoy module
|
||||
- 0c6915_: Bugfix for generating thermal scattering data
|
||||
- 61ecb4_: Fix bugs in Python multipole objects
|
||||
|
||||
.. _c5df6c: https://github.com/mit-crpg/openmc/commit/c5df6c
|
||||
.. _1cfa39: https://github.com/mit-crpg/openmc/commit/1cfa39
|
||||
.. _335359: https://github.com/mit-crpg/openmc/commit/335359
|
||||
.. _17c678: https://github.com/mit-crpg/openmc/commit/17c678
|
||||
.. _23ec0b: https://github.com/mit-crpg/openmc/commit/23ec0b
|
||||
.. _7eefb7: https://github.com/mit-crpg/openmc/commit/7eefb7
|
||||
.. _7880d4: https://github.com/mit-crpg/openmc/commit/7880d4
|
||||
.. _ad2d9f: https://github.com/mit-crpg/openmc/commit/ad2d9f
|
||||
.. _59fdca: https://github.com/mit-crpg/openmc/commit/59fdca
|
||||
.. _9eff5b: https://github.com/mit-crpg/openmc/commit/9eff5b
|
||||
.. _7848a9: https://github.com/mit-crpg/openmc/commit/7848a9
|
||||
.. _f139ce: https://github.com/mit-crpg/openmc/commit/f139ce
|
||||
.. _b8ddfa: https://github.com/mit-crpg/openmc/commit/b8ddfa
|
||||
.. _ec3cfb: https://github.com/mit-crpg/openmc/commit/ec3cfb
|
||||
.. _5e9b06: https://github.com/mit-crpg/openmc/commit/5e9b06
|
||||
.. _c39990: https://github.com/mit-crpg/openmc/commit/c39990
|
||||
.. _c6b67e: https://github.com/mit-crpg/openmc/commit/c6b67e
|
||||
.. _489540: https://github.com/mit-crpg/openmc/commit/489540
|
||||
.. _f0214f: https://github.com/mit-crpg/openmc/commit/f0214f
|
||||
.. _937469: https://github.com/mit-crpg/openmc/commit/937469
|
||||
.. _a149ef: https://github.com/mit-crpg/openmc/commit/a149ef
|
||||
.. _2c9b21: https://github.com/mit-crpg/openmc/commit/2c9b21
|
||||
.. _8047f6: https://github.com/mit-crpg/openmc/commit/8047f6
|
||||
.. _0beb4c: https://github.com/mit-crpg/openmc/commit/0beb4c
|
||||
.. _f124be: https://github.com/mit-crpg/openmc/commit/f124be
|
||||
.. _0c6915: https://github.com/mit-crpg/openmc/commit/0c6915
|
||||
.. _61ecb4: https://github.com/mit-crpg/openmc/commit/61ecb4
|
||||
|
||||
------------
|
||||
Contributors
|
||||
|
|
@ -139,14 +86,19 @@ Contributors
|
|||
|
||||
This release contains new contributions from the following people:
|
||||
|
||||
- `Brody Bassett <brbass@umich.edu>`_
|
||||
- `Will Boyd <wbinventor@gmail.com>`_
|
||||
- `Guillaume Giudicelli <g_giud@mit.edu>`_
|
||||
- `Brittany Grayson <graybri3@isu.edu>`_
|
||||
- `Sterling Harper <sterlingmharper@gmail.com>`_
|
||||
- `Qingming He <906459647@qq.com>`_
|
||||
- `Colin Josey <cjosey@mit.edu>`_
|
||||
- `Travis Labossiere-Hickman <tjlaboss@mit.edu>`_
|
||||
- `Jingang Liang <liangjg2008@gmail.com>`_
|
||||
- `Alex Lindsay <alexlindsay239@gmail.com>`_
|
||||
- `Johnny Liu <johnny16.21@gmail.com>`_
|
||||
- `Amanda Lund <alund@anl.gov>`_
|
||||
- `April Novak <novak@berkeley.edu>`_
|
||||
- `Adam Nelson <nelsonag@umich.edu>`_
|
||||
- `Jose Salcedo Perez <salcedop@mit.edu>`_
|
||||
- `Paul Romano <paul.k.romano@gmail.com>`_
|
||||
- `Sam Shaner <samuelshaner@gmail.com>`_
|
||||
- `Jon Walsh <jonathan.a.walsh@gmail.com>`_
|
||||
|
|
|
|||
|
|
@ -151,8 +151,8 @@ and `Volume II`_. You may also find it helpful to review the following terms:
|
|||
.. _git: http://git-scm.com/
|
||||
.. _git tutorials: http://git-scm.com/documentation
|
||||
.. _Reactor Concepts Manual: http://www.tayloredge.com/periodic/trivia/ReactorConcepts.pdf
|
||||
.. _Volume I: http://energy.gov/sites/prod/files/2013/06/f2/h1019v1.pdf
|
||||
.. _Volume II: http://energy.gov/sites/prod/files/2013/06/f2/h1019v2.pdf
|
||||
.. _Volume I: https://www.standards.doe.gov/standards-documents/1000/1019-bhdbk-1993-v1
|
||||
.. _Volume II: https://www.standards.doe.gov/standards-documents/1000/1019-bhdbk-1993-v2
|
||||
.. _OpenMC source code: https://github.com/mit-crpg/openmc
|
||||
.. _GitHub: https://github.com/
|
||||
.. _bug reports: https://github.com/mit-crpg/openmc/issues
|
||||
|
|
|
|||
|
|
@ -222,6 +222,13 @@ named ``njoy`` available on your path. If you want to explicitly name the
|
|||
executable, the ``njoy_exec`` optional argument can be used. Additionally, the
|
||||
``stdout`` argument can be used to show the progress of the NJOY run.
|
||||
|
||||
To generate a thermal scattering file, you need to specify both an ENDF incident
|
||||
neutron sub-library file as well as a thermal neutron scattering sub-library
|
||||
file; for example::
|
||||
|
||||
light_water = openmc.data.ThermalScattering.from_njoy(
|
||||
'neutrons/n-001_H_001.endf', 'thermal_scatt/tsl-HinH2O.endf')
|
||||
|
||||
Once you have instances of :class:`IncidentNeutron` and
|
||||
:class:`ThermalScattering`, a library can be created by using the
|
||||
``export_to_hdf5()`` methods and the :class:`DataLibrary` class as described in
|
||||
|
|
|
|||
|
|
@ -6,17 +6,18 @@ Installation and Configuration
|
|||
|
||||
.. currentmodule:: openmc
|
||||
|
||||
.. _install_conda:
|
||||
|
||||
----------------------------------------
|
||||
Installing on Linux/Mac with conda-forge
|
||||
----------------------------------------
|
||||
|
||||
`Conda <http://conda.pydata.org/docs/>`_ is an open source package management
|
||||
system and environment management system for installing multiple versions of
|
||||
software packages and their dependencies and switching easily between
|
||||
them. `conda-forge <https://conda-forge.github.io/>`_ is a community-led conda
|
||||
channel of installable packages. For instructions on installing conda, please
|
||||
consult their `documentation
|
||||
<http://conda.pydata.org/docs/install/quick.html>`_.
|
||||
Conda_ is an open source package management system and environment management
|
||||
system for installing multiple versions of software packages and their
|
||||
dependencies and switching easily between them. `conda-forge
|
||||
<https://conda-forge.github.io/>`_ is a community-led conda channel of
|
||||
installable packages. For instructions on installing conda, please consult their
|
||||
`documentation <http://conda.pydata.org/docs/install/quick.html>`_.
|
||||
|
||||
Once you have `conda` installed on your system, add the `conda-forge` channel to
|
||||
your configuration with:
|
||||
|
|
@ -38,6 +39,8 @@ It is possible to list all of the versions of OpenMC available on your platform
|
|||
|
||||
conda search openmc --channel conda-forge
|
||||
|
||||
.. _install_ppa:
|
||||
|
||||
-----------------------------
|
||||
Installing on Ubuntu with PPA
|
||||
-----------------------------
|
||||
|
|
@ -68,9 +71,11 @@ are no longer supported.
|
|||
.. _Personal Package Archive: https://launchpad.net/~paulromano/+archive/staging
|
||||
.. _APT package manager: https://help.ubuntu.com/community/AptGet/Howto
|
||||
|
||||
--------------------
|
||||
Building from Source
|
||||
--------------------
|
||||
.. _install_source:
|
||||
|
||||
----------------------
|
||||
Installing from Source
|
||||
----------------------
|
||||
|
||||
.. _prerequisites:
|
||||
|
||||
|
|
@ -95,10 +100,10 @@ Prerequisites
|
|||
|
||||
* A C/C++ compiler such as gcc_
|
||||
|
||||
OpenMC includes two libraries written in C and C++, respectively. These
|
||||
libraries have been tested to work with a wide variety of compilers. If
|
||||
you are using a Debian-based distribution, you can install the g++
|
||||
compiler using the following command::
|
||||
OpenMC includes various source files written in C and C++,
|
||||
respectively. These source files have been tested to work with a wide
|
||||
variety of compilers. If you are using a Debian-based distribution, you
|
||||
can install the g++ compiler using the following command::
|
||||
|
||||
sudo apt install g++
|
||||
|
||||
|
|
@ -113,34 +118,38 @@ Prerequisites
|
|||
|
||||
* 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::
|
||||
OpenMC uses HDF5 for many input/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 compiling with gcc from the APT repositories, users of Debian
|
||||
derivatives can install HDF5 and/or parallel HDF5 through the package
|
||||
manager::
|
||||
|
||||
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
|
||||
sudo apt install libhdf5-dev
|
||||
|
||||
Parallel versions of the HDF5 library called `libhdf5-mpich-dev` and
|
||||
`libhdf5-openmpi-dev` exist which are built against MPICH and OpenMPI,
|
||||
respectively. To link against a parallel HDF5 library, make sure to set
|
||||
the HDF5_PREFER_PARALLEL CMake option, e.g.::
|
||||
|
||||
FC=mpifort.mpich cmake -DHDF5_PREFER_PARALLEL=on ..
|
||||
|
||||
Note that the exact package names may vary depending on your particular
|
||||
distribution and version.
|
||||
|
||||
If you are using building HDF5 from source 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=mpifort ./configure --enable-fortran --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 install libhdf5-dev hdf5-helpers
|
||||
|
||||
Note that the exact package names may vary depending on your particular
|
||||
distribution and version.
|
||||
If you are building HDF5 version 1.8.x or earlier, you must include
|
||||
``--enable-fortran2003`` when configuring HDF5 or else OpenMC will not
|
||||
be able to compile.
|
||||
|
||||
.. admonition:: Optional
|
||||
:class: note
|
||||
|
|
@ -163,7 +172,7 @@ Prerequisites
|
|||
.. _CMake: http://www.cmake.org
|
||||
.. _OpenMPI: http://www.open-mpi.org
|
||||
.. _MPICH: http://www.mpich.org
|
||||
.. _HDF5: http://www.hdfgroup.org/HDF5/
|
||||
.. _HDF5: https://www.hdfgroup.org/solutions/hdf5/
|
||||
|
||||
Obtaining the Source
|
||||
--------------------
|
||||
|
|
@ -187,8 +196,8 @@ switch to the source of the latest stable release, run the following commands::
|
|||
git checkout master
|
||||
|
||||
.. _GitHub: https://github.com/mit-crpg/openmc
|
||||
.. _git: http://git-scm.com
|
||||
.. _ssh: http://en.wikipedia.org/wiki/Secure_Shell
|
||||
.. _git: https://git-scm.com
|
||||
.. _ssh: https://en.wikipedia.org/wiki/Secure_Shell
|
||||
|
||||
.. _usersguide_build:
|
||||
|
||||
|
|
@ -254,14 +263,15 @@ should be used:
|
|||
Compiling with MPI
|
||||
++++++++++++++++++
|
||||
|
||||
To compile with MPI, set the :envvar:`FC` and :envvar:`CC` environment variables
|
||||
to the path to the MPI Fortran and C wrappers, respectively. For example, in a
|
||||
bash shell:
|
||||
To compile with MPI, set the :envvar:`FC`, :envvar:`CC`, and :envvar:`CXX`
|
||||
environment variables to the path to the MPI Fortran, C, and C++ wrappers,
|
||||
respectively. For example, in a bash shell:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
export FC=mpif90
|
||||
export FC=mpifort
|
||||
export CC=mpicc
|
||||
export CXX=mpicxx
|
||||
cmake /path/to/openmc
|
||||
|
||||
Note that in many shells, environment variables can be set for a single command,
|
||||
|
|
@ -269,7 +279,7 @@ i.e.
|
|||
|
||||
.. code-block:: sh
|
||||
|
||||
FC=mpif90 CC=mpicc cmake /path/to/openmc
|
||||
FC=mpifort CC=mpicc CXX=mpicxx cmake /path/to/openmc
|
||||
|
||||
Selecting HDF5 Installation
|
||||
+++++++++++++++++++++++++++
|
||||
|
|
@ -345,7 +355,7 @@ follows:
|
|||
.. code-block:: sh
|
||||
|
||||
mkdir build && cd build
|
||||
FC=ifort CC=icc FFLAGS=-mmic cmake -Dopenmp=on ..
|
||||
FC=ifort CC=icc CXX=icpc FFLAGS=-mmic cmake -Dopenmp=on ..
|
||||
make
|
||||
|
||||
Note that unless an HDF5 build for the Intel Xeon Phi (Knights Corner) is
|
||||
|
|
@ -358,45 +368,59 @@ workarounds.
|
|||
Testing Build
|
||||
-------------
|
||||
|
||||
If you have ENDF/B-VII.1 cross sections from NNDC_ you can test your build.
|
||||
Make sure the **OPENMC_CROSS_SECTIONS** environmental variable is set to the
|
||||
*cross_sections.xml* file in the *data/nndc* directory.
|
||||
There are two ways to run tests. The first is to use the Makefile present in
|
||||
the source directory and run the following:
|
||||
To run the test suite, you will first need to download a pre-generated cross
|
||||
section library along with windowed multipole data. Please refer to our
|
||||
:ref:`devguide_tests` documentation for further details.
|
||||
|
||||
---------------------
|
||||
Installing Python API
|
||||
---------------------
|
||||
|
||||
If you installed OpenMC using :ref:`Conda <install_conda>` or :ref:`PPA
|
||||
<install_ppa>`, no further steps are necessary in order to use OpenMC's
|
||||
:ref:`Python API <pythonapi>`. However, if you are :ref:`installing from source
|
||||
<install_source>`, the Python API is not installed by default when ``make
|
||||
install`` is run because in many situations it doesn't make sense to install a
|
||||
Python package in the same location as the ``openmc`` executable (for example,
|
||||
if you are installing the package into a `virtual environment
|
||||
<https://docs.python.org/3/tutorial/venv.html>`_). The easiest way to install
|
||||
the :mod:`openmc` Python package is to use pip_, which is included by default in
|
||||
Python 3.4+. From the root directory of the OpenMC distribution/repository, run:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
make test
|
||||
pip install .
|
||||
|
||||
If you want more options for testing you can use ctest_ command. For example,
|
||||
if we wanted to run only the plot tests with 4 processors, we run:
|
||||
pip will first check that all :ref:`required third-party packages
|
||||
<usersguide_python_prereqs>` have been installed, and if they are not present,
|
||||
they will be installed by downloading the appropriate packages from the Python
|
||||
Package Index (`PyPI <https://pypi.org/>`_). However, do note that since pip
|
||||
runs the ``setup.py`` script which requires NumPy, you will have to first
|
||||
install NumPy:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
cd build
|
||||
ctest -j 4 -R plot
|
||||
pip install numpy
|
||||
|
||||
If you want to run the full test suite with different build options please
|
||||
refer to our :ref:`test suite` documentation.
|
||||
Installing in "Development" Mode
|
||||
--------------------------------
|
||||
|
||||
--------------------
|
||||
Python Prerequisites
|
||||
--------------------
|
||||
If you are primarily doing development with OpenMC, it is strongly recommended
|
||||
to install the Python package in :ref:`"editable" mode <devguide_editable>`.
|
||||
|
||||
OpenMC's :ref:`Python API <pythonapi>` works with either Python 2.7 or Python
|
||||
3.2+. In addition to Python itself, the API relies on a number of third-party
|
||||
packages. All prerequisites can be installed using `conda
|
||||
<http://conda.pydata.org/docs/>`_ (recommended), `pip
|
||||
<https://pip.pypa.io/en/stable/>`_, or through the package manager in most Linux
|
||||
.. _usersguide_python_prereqs:
|
||||
|
||||
Prerequisites
|
||||
-------------
|
||||
|
||||
The Python API works with Python 3.4+. In addition to Python itself, the API
|
||||
relies on a number of third-party packages. All prerequisites can be installed
|
||||
using Conda_ (recommended), pip_, or through the package manager in most Linux
|
||||
distributions.
|
||||
|
||||
.. admonition:: Required
|
||||
:class: error
|
||||
|
||||
`six <https://pythonhosted.org/six/>`_
|
||||
The Python API works with both Python 2.7+ and 3.2+. To do so, the six
|
||||
compatibility library is used.
|
||||
|
||||
`NumPy <http://www.numpy.org/>`_
|
||||
NumPy is used extensively within the Python API for its powerful
|
||||
N-dimensional array.
|
||||
|
|
@ -428,6 +452,11 @@ distributions.
|
|||
.. admonition:: Optional
|
||||
:class: note
|
||||
|
||||
`mpi4py <http://mpi4py.scipy.org/>`_
|
||||
mpi4py provides Python bindings to MPI for running distributed-memory
|
||||
parallel runs. This package is needed if you plan on running depletion
|
||||
simulations in parallel using MPI.
|
||||
|
||||
`Cython <http://cython.org/>`_
|
||||
Cython is used for resonance reconstruction for ENDF data converted to
|
||||
:class:`openmc.data.IncidentNeutron`.
|
||||
|
|
@ -470,3 +499,5 @@ schemas.xml file in your own OpenMC source directory.
|
|||
.. _RELAX NG: http://relaxng.org/
|
||||
.. _NNDC: http://www.nndc.bnl.gov/endf/b7.1/acefiles.html
|
||||
.. _ctest: http://www.cmake.org/cmake/help/v2.8.12/ctest.html
|
||||
.. _Conda: https://conda.io/docs/
|
||||
.. _pip: https://pip.pypa.io/en/stable/
|
||||
|
|
|
|||
|
|
@ -168,8 +168,8 @@ ENDF/B-VII.1. It has the following optional arguments:
|
|||
|
||||
This script downloads `ENDF/B-VII.1 ACE data
|
||||
<http://www.nndc.bnl.gov/endf/b7.1/acefiles.html>`_ from NNDC and converts it to
|
||||
an HDF5 library for use with OpenMC. This data is used for OpenMC's regression
|
||||
test suite. This script has the following optional arguments:
|
||||
an HDF5 library for use with OpenMC. This script has the following optional
|
||||
arguments:
|
||||
|
||||
-b, --batch Suppress standard in
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ be specified:
|
|||
'plot'
|
||||
Generates slice or voxel plots (see :ref:`usersguide_plots`).
|
||||
|
||||
'particle_restart'
|
||||
'particle restart'
|
||||
Simulate a single source particle using a particle restart file.
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -148,11 +148,9 @@
|
|||
"source": [
|
||||
"To build the actual 2-D model, we will first begin by creating the `materials.xml` file.\n",
|
||||
"\n",
|
||||
"First we need to define materials that will be used in the problem. In other notebooks, either `openmc.Nuclide`s or `openmc.Element`s were created at the equivalent stage. We can do that in multi-group mode as well. However, multi-group cross-sections are sometimes provided as macroscopic cross-sections; the C5G7 benchmark data are macroscopic. In this case, we can instead use `openmc.Macroscopic` objects to in-place of `openmc.Nuclide` or `openmc.Element` objects.\n",
|
||||
"First we need to define materials that will be used in the problem. In other notebooks, either nuclides or elements were added to materials at the equivalent stage. We can do that in multi-group mode as well. However, multi-group cross-sections are sometimes provided as macroscopic cross-sections; the C5G7 benchmark data are macroscopic. In this case, we can instead use the `Material.add_macroscopic` method to specific a macroscopic object. Unlike for nuclides and elements, we do not need provide information on atom/weight percents as no number densities are needed.\n",
|
||||
"\n",
|
||||
"`openmc.Macroscopic`, unlike `openmc.Nuclide` and `openmc.Element` objects, do not need to be provided enough information to calculate number densities, as no number densities are needed.\n",
|
||||
"\n",
|
||||
"When assigning `openmc.Macroscopic` objects to `openmc.Material` objects, the density can still be scaled by setting the density to a value that is not 1.0. This would be useful, for example, when slightly perturbing the density of water due to a small change in temperature (while of course ignoring any resultant spectral shift). The density of a macroscopic dataset is set to 1.0 in the `openmc.Material` object by default when an `openmc.Macroscopic` dataset is used; so we will show its use the first time and then afterwards it will not be required.\n",
|
||||
"When assigning macroscopic objects to a material, the density can still be scaled by setting the density to a value that is not 1.0. This would be useful, for example, when slightly perturbing the density of water due to a small change in temperature (while of course ignoring any resultant spectral shift). The density of a macroscopic dataset is set to 1.0 in the `openmc.Material` object by default when a macroscopic dataset is used; so we will show its use the first time and then afterwards it will not be required.\n",
|
||||
"\n",
|
||||
"Aside from these differences, the following code is very similar to similar code in other OpenMC example Notebooks."
|
||||
]
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -151,7 +151,7 @@
|
|||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"First we need to define materials that will be used in the problem. Before defining a material, we must create nuclides that are used in the material."
|
||||
"We being by creating a material for the homogeneous medium."
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -161,38 +161,15 @@
|
|||
"collapsed": true
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Instantiate some Nuclides\n",
|
||||
"h1 = openmc.Nuclide('H1')\n",
|
||||
"o16 = openmc.Nuclide('O16')\n",
|
||||
"u235 = openmc.Nuclide('U235')\n",
|
||||
"u238 = openmc.Nuclide('U238')\n",
|
||||
"zr90 = openmc.Nuclide('Zr90')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"With the nuclides we defined, we will now create a material for the homogeneous medium."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Instantiate a Material and register the Nuclides\n",
|
||||
"inf_medium = openmc.Material(name='moderator')\n",
|
||||
"inf_medium.set_density('g/cc', 5.)\n",
|
||||
"inf_medium.add_nuclide(h1, 0.028999667)\n",
|
||||
"inf_medium.add_nuclide(o16, 0.01450188)\n",
|
||||
"inf_medium.add_nuclide(u235, 0.000114142)\n",
|
||||
"inf_medium.add_nuclide(u238, 0.006886019)\n",
|
||||
"inf_medium.add_nuclide(zr90, 0.002116053)"
|
||||
"inf_medium.add_nuclide('H1', 0.028999667)\n",
|
||||
"inf_medium.add_nuclide('O16', 0.01450188)\n",
|
||||
"inf_medium.add_nuclide('U235', 0.000114142)\n",
|
||||
"inf_medium.add_nuclide('U238', 0.006886019)\n",
|
||||
"inf_medium.add_nuclide('Zr90', 0.002116053)"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -204,7 +181,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"execution_count": 4,
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
|
|
@ -224,7 +201,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"execution_count": 5,
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
|
|
@ -246,7 +223,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"execution_count": 6,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
|
|
@ -271,15 +248,14 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 8,
|
||||
"execution_count": 7,
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Instantiate Universe\n",
|
||||
"root_universe = openmc.Universe(universe_id=0, name='root universe')\n",
|
||||
"root_universe.add_cell(cell)"
|
||||
"# Create root universe\n",
|
||||
"root_universe = openmc.Universe(name='root universe', cells=[cell])"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -291,15 +267,14 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 9,
|
||||
"execution_count": 8,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Create Geometry and set root Universe\n",
|
||||
"openmc_geometry = openmc.Geometry()\n",
|
||||
"openmc_geometry.root_universe = root_universe\n",
|
||||
"openmc_geometry = openmc.Geometry(root_universe)\n",
|
||||
"\n",
|
||||
"# Export to \"geometry.xml\"\n",
|
||||
"openmc_geometry.export_to_xml()"
|
||||
|
|
@ -314,7 +289,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 10,
|
||||
"execution_count": 9,
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
|
|
@ -350,7 +325,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 11,
|
||||
"execution_count": 10,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
|
|
@ -389,7 +364,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 12,
|
||||
"execution_count": 11,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
|
|
@ -414,7 +389,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 13,
|
||||
"execution_count": 12,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
|
|
@ -423,13 +398,13 @@
|
|||
"data": {
|
||||
"text/plain": [
|
||||
"OrderedDict([('flux', Tally\n",
|
||||
" \tID =\t10000\n",
|
||||
" \tID =\t1\n",
|
||||
" \tName =\t\n",
|
||||
" \tFilters =\tCellFilter, EnergyFilter\n",
|
||||
" \tNuclides =\ttotal \n",
|
||||
" \tScores =\t['flux']\n",
|
||||
" \tEstimator =\ttracklength), ('absorption', Tally\n",
|
||||
" \tID =\t10001\n",
|
||||
" \tID =\t2\n",
|
||||
" \tName =\t\n",
|
||||
" \tFilters =\tCellFilter, EnergyFilter\n",
|
||||
" \tNuclides =\ttotal \n",
|
||||
|
|
@ -437,7 +412,7 @@
|
|||
" \tEstimator =\ttracklength)])"
|
||||
]
|
||||
},
|
||||
"execution_count": 13,
|
||||
"execution_count": 12,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
|
@ -455,11 +430,22 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 14,
|
||||
"execution_count": 13,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stderr",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"/home/romano/openmc/openmc/mixin.py:61: IDWarning: Another CellFilter instance already exists with id=3.\n",
|
||||
" warn(msg, IDWarning)\n",
|
||||
"/home/romano/openmc/openmc/mixin.py:61: IDWarning: Another EnergyFilter instance already exists with id=4.\n",
|
||||
" warn(msg, IDWarning)\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"# Instantiate an empty Tallies object\n",
|
||||
"tallies_file = openmc.Tallies()\n",
|
||||
|
|
@ -486,7 +472,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 15,
|
||||
"execution_count": 14,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
|
|
@ -523,37 +509,27 @@
|
|||
" | The OpenMC Monte Carlo Code\n",
|
||||
" Copyright | 2011-2017 Massachusetts Institute of Technology\n",
|
||||
" License | http://openmc.readthedocs.io/en/latest/license.html\n",
|
||||
" Version | 0.8.0\n",
|
||||
" Git SHA1 | 43b141e9ba542da8b28c078cf2df8a6777cfb2ad\n",
|
||||
" Date/Time | 2017-02-28 11:52:00\n",
|
||||
" Version | 0.9.0\n",
|
||||
" Git SHA1 | 9b7cebf7bc34d60e0f1750c3d6cb103df11e8dc4\n",
|
||||
" Date/Time | 2017-12-04 20:56:46\n",
|
||||
" OpenMP Threads | 4\n",
|
||||
"\n",
|
||||
" ===========================================================================\n",
|
||||
" ========================> INITIALIZATION <=========================\n",
|
||||
" ===========================================================================\n",
|
||||
"\n",
|
||||
" Reading settings XML file...\n",
|
||||
" Reading geometry XML file...\n",
|
||||
" Reading materials XML file...\n",
|
||||
" Reading cross sections XML file...\n",
|
||||
" Reading H1 from\n",
|
||||
" /home/wbinventor/Documents/NSE-CRPG-Codes/openmc/data/nndc_hdf5/H1.h5\n",
|
||||
" Reading O16 from\n",
|
||||
" /home/wbinventor/Documents/NSE-CRPG-Codes/openmc/data/nndc_hdf5/O16.h5\n",
|
||||
" Reading U235 from\n",
|
||||
" /home/wbinventor/Documents/NSE-CRPG-Codes/openmc/data/nndc_hdf5/U235.h5\n",
|
||||
" Reading U238 from\n",
|
||||
" /home/wbinventor/Documents/NSE-CRPG-Codes/openmc/data/nndc_hdf5/U238.h5\n",
|
||||
" Reading Zr90 from\n",
|
||||
" /home/wbinventor/Documents/NSE-CRPG-Codes/openmc/data/nndc_hdf5/Zr90.h5\n",
|
||||
" Reading materials XML file...\n",
|
||||
" Reading geometry XML file...\n",
|
||||
" Building neighboring cells lists for each surface...\n",
|
||||
" Reading H1 from /home/romano/openmc/scripts/nndc_hdf5/H1.h5\n",
|
||||
" Reading O16 from /home/romano/openmc/scripts/nndc_hdf5/O16.h5\n",
|
||||
" Reading U235 from /home/romano/openmc/scripts/nndc_hdf5/U235.h5\n",
|
||||
" Reading U238 from /home/romano/openmc/scripts/nndc_hdf5/U238.h5\n",
|
||||
" Reading Zr90 from /home/romano/openmc/scripts/nndc_hdf5/Zr90.h5\n",
|
||||
" Maximum neutron transport energy: 2.00000E+07 eV for H1\n",
|
||||
" Reading tallies XML file...\n",
|
||||
" Building neighboring cells lists for each surface...\n",
|
||||
" Writing summary.h5 file...\n",
|
||||
" Initializing source particles...\n",
|
||||
"\n",
|
||||
" ===========================================================================\n",
|
||||
" ====================> K EIGENVALUE SIMULATION <====================\n",
|
||||
" ===========================================================================\n",
|
||||
"\n",
|
||||
" Bat./Gen. k Average k \n",
|
||||
" ========= ======== ==================== \n",
|
||||
|
|
@ -609,27 +585,22 @@
|
|||
" 50/1 1.15798 1.16146 +/- 0.00457\n",
|
||||
" Creating state point statepoint.50.h5...\n",
|
||||
"\n",
|
||||
" ===========================================================================\n",
|
||||
" ======================> SIMULATION FINISHED <======================\n",
|
||||
" ===========================================================================\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" =======================> TIMING STATISTICS <=======================\n",
|
||||
"\n",
|
||||
" Total time for initialization = 3.0114E-01 seconds\n",
|
||||
" Reading cross sections = 1.8743E-01 seconds\n",
|
||||
" Total time in simulation = 9.7641E+00 seconds\n",
|
||||
" Time in transport only = 9.5168E+00 seconds\n",
|
||||
" Time in inactive batches = 1.2602E+00 seconds\n",
|
||||
" Time in active batches = 8.5039E+00 seconds\n",
|
||||
" Time synchronizing fission bank = 5.4293E-03 seconds\n",
|
||||
" Sampling source sites = 4.3508E-03 seconds\n",
|
||||
" SEND/RECV source sites = 9.9399E-04 seconds\n",
|
||||
" Time accumulating tallies = 1.2758E-04 seconds\n",
|
||||
" Total time for finalization = 3.6982E-04 seconds\n",
|
||||
" Total time elapsed = 1.0075E+01 seconds\n",
|
||||
" Calculation Rate (inactive) = 19838.7 neutrons/second\n",
|
||||
" Calculation Rate (active) = 11759.3 neutrons/second\n",
|
||||
" Total time for initialization = 4.0504E-01 seconds\n",
|
||||
" Reading cross sections = 3.6457E-01 seconds\n",
|
||||
" Total time in simulation = 6.3478E+00 seconds\n",
|
||||
" Time in transport only = 6.0079E+00 seconds\n",
|
||||
" Time in inactive batches = 8.1713E-01 seconds\n",
|
||||
" Time in active batches = 5.5307E+00 seconds\n",
|
||||
" Time synchronizing fission bank = 5.4640E-03 seconds\n",
|
||||
" Sampling source sites = 4.0981E-03 seconds\n",
|
||||
" SEND/RECV source sites = 1.2606E-03 seconds\n",
|
||||
" Time accumulating tallies = 1.2030E-04 seconds\n",
|
||||
" Total time for finalization = 9.6554E-04 seconds\n",
|
||||
" Total time elapsed = 6.7713E+00 seconds\n",
|
||||
" Calculation Rate (inactive) = 30594.8 neutrons/second\n",
|
||||
" Calculation Rate (active) = 18080.8 neutrons/second\n",
|
||||
"\n",
|
||||
" ============================> RESULTS <============================\n",
|
||||
"\n",
|
||||
|
|
@ -647,7 +618,7 @@
|
|||
"0"
|
||||
]
|
||||
},
|
||||
"execution_count": 15,
|
||||
"execution_count": 14,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
|
@ -673,7 +644,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 16,
|
||||
"execution_count": 15,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
|
|
@ -699,7 +670,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 17,
|
||||
"execution_count": 16,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
|
|
@ -734,7 +705,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 18,
|
||||
"execution_count": 17,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
|
|
@ -769,7 +740,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 19,
|
||||
"execution_count": 18,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
|
|
@ -816,7 +787,7 @@
|
|||
"0 1 2 total 1.292013 0.007642"
|
||||
]
|
||||
},
|
||||
"execution_count": 19,
|
||||
"execution_count": 18,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
|
@ -835,7 +806,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 20,
|
||||
"execution_count": 19,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
|
|
@ -853,7 +824,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 21,
|
||||
"execution_count": 20,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
|
|
@ -880,7 +851,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 22,
|
||||
"execution_count": 21,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
|
|
@ -920,7 +891,7 @@
|
|||
" <td>2.000000e+07</td>\n",
|
||||
" <td>total</td>\n",
|
||||
" <td>(((total / flux) - (absorption / flux)) - (sca...</td>\n",
|
||||
" <td>1.776357e-15</td>\n",
|
||||
" <td>7.771561e-16</td>\n",
|
||||
" <td>0.002570</td>\n",
|
||||
" </tr>\n",
|
||||
" </tbody>\n",
|
||||
|
|
@ -934,10 +905,10 @@
|
|||
"\n",
|
||||
" score mean std. dev. \n",
|
||||
"0 (((total / flux) - (absorption / flux)) - (sca... -1.11e-15 1.13e-02 \n",
|
||||
"1 (((total / flux) - (absorption / flux)) - (sca... 1.78e-15 2.57e-03 "
|
||||
"1 (((total / flux) - (absorption / flux)) - (sca... 7.77e-16 2.57e-03 "
|
||||
]
|
||||
},
|
||||
"execution_count": 22,
|
||||
"execution_count": 21,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
|
@ -959,7 +930,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 23,
|
||||
"execution_count": 22,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
|
|
@ -1016,7 +987,7 @@
|
|||
"1 ((absorption / flux) / (total / flux)) 1.93e-02 9.46e-05 "
|
||||
]
|
||||
},
|
||||
"execution_count": 23,
|
||||
"execution_count": 22,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
|
@ -1031,7 +1002,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 24,
|
||||
"execution_count": 23,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
|
|
@ -1088,7 +1059,7 @@
|
|||
"1 ((scatter / flux) / (total / flux)) 9.81e-01 3.74e-03 "
|
||||
]
|
||||
},
|
||||
"execution_count": 24,
|
||||
"execution_count": 23,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
|
@ -1110,7 +1081,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 25,
|
||||
"execution_count": 24,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
|
|
@ -1167,7 +1138,7 @@
|
|||
"1 (((absorption / flux) / (total / flux)) + ((sc... 1.00e+00 3.74e-03 "
|
||||
]
|
||||
},
|
||||
"execution_count": 25,
|
||||
"execution_count": 24,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
|
@ -1197,7 +1168,7 @@
|
|||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.5.2"
|
||||
"version": "3.6.0"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -63,31 +63,7 @@
|
|||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"First we need to define materials that will be used in the problem. Before defining a material, we must create nuclides that are used in the material."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Instantiate some Nuclides\n",
|
||||
"h1 = openmc.Nuclide('H1')\n",
|
||||
"b10 = openmc.Nuclide('B10')\n",
|
||||
"o16 = openmc.Nuclide('O16')\n",
|
||||
"u235 = openmc.Nuclide('U235')\n",
|
||||
"u238 = openmc.Nuclide('U238')\n",
|
||||
"zr90 = openmc.Nuclide('Zr90')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"With the nuclides we defined, we will now create three materials for the fuel, water, and cladding of the fuel pins."
|
||||
"First we need to define materials that will be used in the problem. We'll create three materials for the fuel, water, and cladding of the fuel pins."
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -101,21 +77,21 @@
|
|||
"# 1.6 enriched fuel\n",
|
||||
"fuel = openmc.Material(name='1.6% Fuel')\n",
|
||||
"fuel.set_density('g/cm3', 10.31341)\n",
|
||||
"fuel.add_nuclide(u235, 3.7503e-4)\n",
|
||||
"fuel.add_nuclide(u238, 2.2625e-2)\n",
|
||||
"fuel.add_nuclide(o16, 4.6007e-2)\n",
|
||||
"fuel.add_nuclide('U235', 3.7503e-4)\n",
|
||||
"fuel.add_nuclide('U238', 2.2625e-2)\n",
|
||||
"fuel.add_nuclide('O16', 4.6007e-2)\n",
|
||||
"\n",
|
||||
"# borated water\n",
|
||||
"water = openmc.Material(name='Borated Water')\n",
|
||||
"water.set_density('g/cm3', 0.740582)\n",
|
||||
"water.add_nuclide(h1, 4.9457e-2)\n",
|
||||
"water.add_nuclide(o16, 2.4732e-2)\n",
|
||||
"water.add_nuclide(b10, 8.0042e-6)\n",
|
||||
"water.add_nuclide('H1', 4.9457e-2)\n",
|
||||
"water.add_nuclide('O16', 2.4732e-2)\n",
|
||||
"water.add_nuclide('B10', 8.0042e-6)\n",
|
||||
"\n",
|
||||
"# zircaloy\n",
|
||||
"zircaloy = openmc.Material(name='Zircaloy')\n",
|
||||
"zircaloy.set_density('g/cm3', 6.55)\n",
|
||||
"zircaloy.add_nuclide(zr90, 7.2758e-3)"
|
||||
"zircaloy.add_nuclide('Zr90', 7.2758e-3)"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -338,8 +314,7 @@
|
|||
"outputs": [],
|
||||
"source": [
|
||||
"# Create Geometry and set root Universe\n",
|
||||
"geometry = openmc.Geometry()\n",
|
||||
"geometry.root_universe = root_universe"
|
||||
"geometry = openmc.Geometry(root_universe)"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -1679,7 +1654,7 @@
|
|||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.5.2"
|
||||
"version": "3.6.0"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -33,7 +33,7 @@
|
|||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"First we need to define materials that will be used in the problem. Before defining a material, we must create nuclides that are used in the material."
|
||||
"First we need to define materials that will be used in the problem. We'll create three materials for the fuel, water, and cladding of the fuel pin."
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -43,49 +43,25 @@
|
|||
"collapsed": true
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Instantiate some Nuclides\n",
|
||||
"h1 = openmc.Nuclide('H1')\n",
|
||||
"b10 = openmc.Nuclide('B10')\n",
|
||||
"o16 = openmc.Nuclide('O16')\n",
|
||||
"u235 = openmc.Nuclide('U235')\n",
|
||||
"u238 = openmc.Nuclide('U238')\n",
|
||||
"zr90 = openmc.Nuclide('Zr90')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"With the nuclides we defined, we will now create three materials for the fuel, water, and cladding of the fuel pin."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# 1.6 enriched fuel\n",
|
||||
"fuel = openmc.Material(name='1.6% Fuel')\n",
|
||||
"fuel.set_density('g/cm3', 10.31341)\n",
|
||||
"fuel.add_nuclide(u235, 3.7503e-4)\n",
|
||||
"fuel.add_nuclide(u238, 2.2625e-2)\n",
|
||||
"fuel.add_nuclide(o16, 4.6007e-2)\n",
|
||||
"fuel.add_nuclide('U235', 3.7503e-4)\n",
|
||||
"fuel.add_nuclide('U238', 2.2625e-2)\n",
|
||||
"fuel.add_nuclide('O16', 4.6007e-2)\n",
|
||||
"\n",
|
||||
"# borated water\n",
|
||||
"water = openmc.Material(name='Borated Water')\n",
|
||||
"water.set_density('g/cm3', 0.740582)\n",
|
||||
"water.add_nuclide(h1, 4.9457e-2)\n",
|
||||
"water.add_nuclide(o16, 2.4732e-2)\n",
|
||||
"water.add_nuclide(b10, 8.0042e-6)\n",
|
||||
"water.add_nuclide('H1', 4.9457e-2)\n",
|
||||
"water.add_nuclide('O16', 2.4732e-2)\n",
|
||||
"water.add_nuclide('B10', 8.0042e-6)\n",
|
||||
"\n",
|
||||
"# zircaloy\n",
|
||||
"zircaloy = openmc.Material(name='Zircaloy')\n",
|
||||
"zircaloy.set_density('g/cm3', 6.55)\n",
|
||||
"zircaloy.add_nuclide(zr90, 7.2758e-3)"
|
||||
"zircaloy.add_nuclide('Zr90', 7.2758e-3)"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -97,7 +73,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"execution_count": 3,
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
|
|
@ -119,7 +95,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"execution_count": 4,
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
|
|
@ -148,7 +124,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"execution_count": 5,
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
|
|
@ -185,7 +161,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"execution_count": 6,
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
|
|
@ -212,20 +188,19 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 8,
|
||||
"execution_count": 7,
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Create Geometry and set root Universe\n",
|
||||
"geometry = openmc.Geometry()\n",
|
||||
"geometry.root_universe = root_universe"
|
||||
"geometry = openmc.Geometry(root_universe)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 9,
|
||||
"execution_count": 8,
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
|
|
@ -244,7 +219,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 10,
|
||||
"execution_count": 9,
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
|
|
@ -280,7 +255,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 11,
|
||||
"execution_count": 10,
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
|
|
@ -308,8 +283,10 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 12,
|
||||
"metadata": {},
|
||||
"execution_count": 11,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
|
|
@ -317,7 +294,7 @@
|
|||
"0"
|
||||
]
|
||||
},
|
||||
"execution_count": 12,
|
||||
"execution_count": 11,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
|
@ -329,17 +306,19 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 13,
|
||||
"metadata": {},
|
||||
"execution_count": 12,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAPoAAAD6AgMAAAD1grKuAAAABGdBTUEAALGPC/xhBQAAACBjSFJN\nAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAADFBMVEX///9yEhLpgJFNv8Tq\nQYT7AAAAAWJLR0QAiAUdSAAAAAd0SU1FB+EKGA0jE/weoLoAAALKSURBVGje7dpLcqQwDAbgHHE2\nYeEj+D4cwQucBUfo+3CEXoSp8OhuhF70T4qpKXmdr21LogK2Pj7A8QmNP+HDhw8fPnz48Kf6VH9G\n+66vy+je8k19jnf8C5dXIPv86ms56lPdjvaYbyodx3ze+XLE76cXFiD4zPji99z0/AJ4n1lfvJ6f\nnl0A6x+578efMSg1wPr172/jPO5yFXM+Ef78gdblM+WPHyguP//t1/g6pA0wfln+ho/fwgYYn19C\n/xwDvwHGc9OvC+hs37DTrwuwfWanXxdQTC9Mvyygs3wjTL8uwPJpn/tNDbSGz7T0SBEWw4vLXzbQ\n6b6RoveIoO6TvPxlA63qs7z8ZQPF9F+SH22vbX8OQKf5Rtv+EgDNJ3X58wZaxWd1+fMGiuFvir8b\nvjp8J/tGy/6jAmRvhW8fwL3vVT+o3grfPoB7r/IpALI3tz8FoJN84/NV873hB8UnM3xzANtf8nb4\ndwmg3grfFEDJO8JPE0i9Ff4pAYL3pI8mkHor/HMCeO9JH00g9SafEsh7T/ppARBvp48UwJnelT5S\nACd7O31TAlnvKx9SQCd7B58KgPO+8iMFuPWe9E8F8BveWX7bAjzX9y4//Jve+fhsH6Ctv7n8PTzj\nvY/v9gEOHz58+PBX+6v/f/wPvnd54f3j6venE/yl769Xv7+j3x/o98/V32/o9+fl389Xnx+g5x/o\n+Qt6/oOeP6HnX+j5G3z+h54/ouefV5/foufP6Pk3ev4On/+j9w/o/Qd6/4Le/6D3T/D9V67Y/ZsV\nQBq+s+8f0ftP+P41axXguP9NWgDuu/Cdfv+N3r/D9/9TAID+A7T/Ae2/gPs/0P4TtP8F7r9J3AIO\n9P+g/Udw/9Oygbf7r9D+L7j/DO1/Q/vv4P4/tP8Q7n9E+y/h/k+0/xTuf4X7b+H+X7T/+BPuf3aM\n8OHDhw8fPnz4w/4vzcvgeY10sY0AAAAldEVYdGRhdGU6Y3JlYXRlADIwMTctMTAtMjRUMTM6MzU6\nMTktMDU6MDCdcfAWAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE3LTEwLTI0VDEzOjM1OjE5LTA1OjAw\n7CxIqgAAAABJRU5ErkJggg==\n",
|
||||
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAPoAAAD6AgMAAAD1grKuAAAABGdBTUEAALGPC/xhBQAAACBjSFJN\nAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAADFBMVEX///9yEhLpgJFNv8Tq\nQYT7AAAAAWJLR0QAiAUdSAAAAAd0SU1FB+EMBQIrDwapSyIAAALKSURBVGje7dpLcqQwDAbgHHE2\nYeEj+D4cwQucBUfo+3CEXoSp8OhuhF70T4qpKXmdr21LogK2Pj7A8QmNP+HDhw8fPnz48Kf6VH9G\n+66vy+je8k19jnf8C5dXIPv86ms56lPdjvaYbyodx3ze+XLE76cXFiD4zPji99z0/AJ4n1lfvJ6f\nnl0A6x+578efMSg1wPr172/jPO5yFXM+Ef78gdblM+WPHyguP//t1/g6pA0wfln+ho/fwgYYn19C\n/xwDvwHGc9OvC+hs37DTrwuwfWanXxdQTC9Mvyygs3wjTL8uwPJpn/tNDbSGz7T0SBEWw4vLXzbQ\n6b6RoveIoO6TvPxlA63qs7z8ZQPF9F+SH22vbX8OQKf5Rtv+EgDNJ3X58wZaxWd1+fMGiuFvir8b\nvjp8J/tGy/6jAmRvhW8fwL3vVT+o3grfPoB7r/IpALI3tz8FoJN84/NV873hB8UnM3xzANtf8nb4\ndwmg3grfFEDJO8JPE0i9Ff4pAYL3pI8mkHor/HMCeO9JH00g9SafEsh7T/ppARBvp48UwJnelT5S\nACd7O31TAlnvKx9SQCd7B58KgPO+8iMFuPWe9E8F8BveWX7bAjzX9y4//Jve+fhsH6Ctv7n8PTzj\nvY/v9gEOHz58+PBX+6v/f/wPvnd54f3j6venE/yl769Xv7+j3x/o98/V32/o9+fl389Xnx+g5x/o\n+Qt6/oOeP6HnX+j5G3z+h54/ouefV5/foufP6Pk3ev4On/+j9w/o/Qd6/4Le/6D3T/D9V67Y/ZsV\nQBq+s+8f0ftP+P41axXguP9NWgDuu/Cdfv+N3r/D9/9TAID+A7T/Ae2/gPs/0P4TtP8F7r9J3AIO\n9P+g/Udw/9Oygbf7r9D+L7j/DO1/Q/vv4P4/tP8Q7n9E+y/h/k+0/xTuf4X7b+H+X7T/+BPuf3aM\n8OHDhw8fPnz4w/4vzcvgeY10sY0AAAAldEVYdGRhdGU6Y3JlYXRlADIwMTctMTItMDRUMjA6NDM6\nMTQtMDY6MDCrFYTfAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE3LTEyLTA0VDIwOjQzOjE0LTA2OjAw\n2kg8YwAAAABJRU5ErkJggg==\n",
|
||||
"text/plain": [
|
||||
"<IPython.core.display.Image object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 13,
|
||||
"execution_count": 12,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
|
@ -361,7 +340,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 14,
|
||||
"execution_count": 13,
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
|
|
@ -373,7 +352,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 15,
|
||||
"execution_count": 14,
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
|
|
@ -396,7 +375,7 @@
|
|||
"tally.filters = [openmc.CellFilter(fuel_cell)]\n",
|
||||
"tally.filters.append(energy_filter)\n",
|
||||
"tally.scores = ['nu-fission', 'scatter']\n",
|
||||
"tally.nuclides = [u238, u235]\n",
|
||||
"tally.nuclides = ['U238', 'U235']\n",
|
||||
"tallies_file.append(tally)\n",
|
||||
"\n",
|
||||
"# Instantiate reaction rate Tally in moderator\n",
|
||||
|
|
@ -404,7 +383,7 @@
|
|||
"tally.filters = [openmc.CellFilter(moderator_cell)]\n",
|
||||
"tally.filters.append(energy_filter)\n",
|
||||
"tally.scores = ['absorption', 'total']\n",
|
||||
"tally.nuclides = [o16, h1]\n",
|
||||
"tally.nuclides = ['O16', 'H1']\n",
|
||||
"tallies_file.append(tally)\n",
|
||||
"\n",
|
||||
"# Instantiate a tally mesh\n",
|
||||
|
|
@ -434,7 +413,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 16,
|
||||
"execution_count": 15,
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
|
|
@ -450,7 +429,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 17,
|
||||
"execution_count": 16,
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
|
|
@ -465,7 +444,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 18,
|
||||
"execution_count": 17,
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
|
|
@ -481,7 +460,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 19,
|
||||
"execution_count": 18,
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
|
|
@ -496,7 +475,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 20,
|
||||
"execution_count": 19,
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
|
|
@ -510,23 +489,21 @@
|
|||
"tally.filters = [openmc.CellFilter([fuel_cell, moderator_cell])]\n",
|
||||
"tally.filters.append(fine_energy_filter)\n",
|
||||
"tally.scores = ['nu-fission', 'scatter']\n",
|
||||
"tally.nuclides = [h1, u238]\n",
|
||||
"tally.nuclides = ['H1', 'U238']\n",
|
||||
"tallies_file.append(tally)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 21,
|
||||
"metadata": {},
|
||||
"execution_count": 20,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stderr",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"/home/romano/openmc/openmc/mixin.py:61: IDWarning: Another EnergyFilter instance already exists with id=1.\n",
|
||||
" warn(msg, IDWarning)\n",
|
||||
"/home/romano/openmc/openmc/mixin.py:61: IDWarning: Another MeshFilter instance already exists with id=5.\n",
|
||||
" warn(msg, IDWarning)\n",
|
||||
"/home/romano/openmc/openmc/mixin.py:61: IDWarning: Another EnergyFilter instance already exists with id=6.\n",
|
||||
" warn(msg, IDWarning)\n",
|
||||
"/home/romano/openmc/openmc/mixin.py:61: IDWarning: Another CellFilter instance already exists with id=3.\n",
|
||||
|
|
@ -550,8 +527,9 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 22,
|
||||
"execution_count": 21,
|
||||
"metadata": {
|
||||
"collapsed": false,
|
||||
"scrolled": true
|
||||
},
|
||||
"outputs": [
|
||||
|
|
@ -588,13 +566,13 @@
|
|||
" Copyright | 2011-2017 Massachusetts Institute of Technology\n",
|
||||
" License | http://openmc.readthedocs.io/en/latest/license.html\n",
|
||||
" Version | 0.9.0\n",
|
||||
" Git SHA1 | 5ca1d06b0c6ac3b56060ef289b7e5215210e7332\n",
|
||||
" Date/Time | 2017-10-24 13:35:19\n",
|
||||
" Git SHA1 | 9b7cebf7bc34d60e0f1750c3d6cb103df11e8dc4\n",
|
||||
" Date/Time | 2017-12-04 20:43:15\n",
|
||||
" OpenMP Threads | 4\n",
|
||||
"\n",
|
||||
" Reading settings XML file...\n",
|
||||
" Reading materials XML file...\n",
|
||||
" Reading cross sections XML file...\n",
|
||||
" Reading materials XML file...\n",
|
||||
" Reading geometry XML file...\n",
|
||||
" Building neighboring cells lists for each surface...\n",
|
||||
" Reading U235 from /home/romano/openmc/scripts/nndc_hdf5/U235.h5\n",
|
||||
|
|
@ -605,6 +583,7 @@
|
|||
" Reading Zr90 from /home/romano/openmc/scripts/nndc_hdf5/Zr90.h5\n",
|
||||
" Maximum neutron transport energy: 2.00000E+07 eV for U235\n",
|
||||
" Reading tallies XML file...\n",
|
||||
" Writing summary.h5 file...\n",
|
||||
" Initializing source particles...\n",
|
||||
"\n",
|
||||
" ====================> K EIGENVALUE SIMULATION <====================\n",
|
||||
|
|
@ -635,20 +614,20 @@
|
|||
"\n",
|
||||
" =======================> TIMING STATISTICS <=======================\n",
|
||||
"\n",
|
||||
" Total time for initialization = 4.1497E-01 seconds\n",
|
||||
" Reading cross sections = 3.6232E-01 seconds\n",
|
||||
" Total time in simulation = 3.6447E+00 seconds\n",
|
||||
" Time in transport only = 3.5939E+00 seconds\n",
|
||||
" Time in inactive batches = 4.4241E-01 seconds\n",
|
||||
" Time in active batches = 3.2022E+00 seconds\n",
|
||||
" Time synchronizing fission bank = 2.7734E-03 seconds\n",
|
||||
" Sampling source sites = 1.1981E-03 seconds\n",
|
||||
" SEND/RECV source sites = 1.5506E-03 seconds\n",
|
||||
" Time accumulating tallies = 1.2237E-04 seconds\n",
|
||||
" Total time for finalization = 1.4924E-03 seconds\n",
|
||||
" Total time elapsed = 4.0823E+00 seconds\n",
|
||||
" Calculation Rate (inactive) = 28254.0 neutrons/second\n",
|
||||
" Calculation Rate (active) = 11710.5 neutrons/second\n",
|
||||
" Total time for initialization = 5.6782E-01 seconds\n",
|
||||
" Reading cross sections = 5.3276E-01 seconds\n",
|
||||
" Total time in simulation = 6.4149E+00 seconds\n",
|
||||
" Time in transport only = 6.2767E+00 seconds\n",
|
||||
" Time in inactive batches = 6.8747E-01 seconds\n",
|
||||
" Time in active batches = 5.7274E+00 seconds\n",
|
||||
" Time synchronizing fission bank = 2.7492E-03 seconds\n",
|
||||
" Sampling source sites = 1.9584E-03 seconds\n",
|
||||
" SEND/RECV source sites = 7.4113E-04 seconds\n",
|
||||
" Time accumulating tallies = 1.0576E-04 seconds\n",
|
||||
" Total time for finalization = 2.2075E-03 seconds\n",
|
||||
" Total time elapsed = 7.0056E+00 seconds\n",
|
||||
" Calculation Rate (inactive) = 18182.5 neutrons/second\n",
|
||||
" Calculation Rate (active) = 6547.45 neutrons/second\n",
|
||||
"\n",
|
||||
" ============================> RESULTS <============================\n",
|
||||
"\n",
|
||||
|
|
@ -666,15 +645,12 @@
|
|||
"0"
|
||||
]
|
||||
},
|
||||
"execution_count": 22,
|
||||
"execution_count": 21,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"# Remove old HDF5 (summary, statepoint) files\n",
|
||||
"!rm statepoint.*\n",
|
||||
"\n",
|
||||
"# Run OpenMC!\n",
|
||||
"openmc.run()"
|
||||
]
|
||||
|
|
@ -695,7 +671,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 23,
|
||||
"execution_count": 22,
|
||||
"metadata": {
|
||||
"collapsed": true,
|
||||
"scrolled": true
|
||||
|
|
@ -717,26 +693,15 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 24,
|
||||
"metadata": {},
|
||||
"execution_count": 23,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<div>\n",
|
||||
"<style>\n",
|
||||
" .dataframe thead tr:only-child th {\n",
|
||||
" text-align: right;\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" .dataframe thead th {\n",
|
||||
" text-align: left;\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" .dataframe tbody tr th {\n",
|
||||
" vertical-align: top;\n",
|
||||
" }\n",
|
||||
"</style>\n",
|
||||
"<table border=\"1\" class=\"dataframe\">\n",
|
||||
" <thead>\n",
|
||||
" <tr style=\"text-align: right;\">\n",
|
||||
|
|
@ -764,7 +729,7 @@
|
|||
"0 total (nu-fission / (absorption + current)) 1.02e+00 6.65e-03"
|
||||
]
|
||||
},
|
||||
"execution_count": 24,
|
||||
"execution_count": 23,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
|
@ -795,26 +760,15 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 25,
|
||||
"metadata": {},
|
||||
"execution_count": 24,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<div>\n",
|
||||
"<style>\n",
|
||||
" .dataframe thead tr:only-child th {\n",
|
||||
" text-align: right;\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" .dataframe thead th {\n",
|
||||
" text-align: left;\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" .dataframe tbody tr th {\n",
|
||||
" vertical-align: top;\n",
|
||||
" }\n",
|
||||
"</style>\n",
|
||||
"<table border=\"1\" class=\"dataframe\">\n",
|
||||
" <thead>\n",
|
||||
" <tr style=\"text-align: right;\">\n",
|
||||
|
|
@ -849,7 +803,7 @@
|
|||
"0 ((absorption + current) / (absorption + current)) 6.94e-01 4.61e-03 "
|
||||
]
|
||||
},
|
||||
"execution_count": 25,
|
||||
"execution_count": 24,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
|
@ -874,26 +828,15 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 26,
|
||||
"metadata": {},
|
||||
"execution_count": 25,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<div>\n",
|
||||
"<style>\n",
|
||||
" .dataframe thead tr:only-child th {\n",
|
||||
" text-align: right;\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" .dataframe thead th {\n",
|
||||
" text-align: left;\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" .dataframe tbody tr th {\n",
|
||||
" vertical-align: top;\n",
|
||||
" }\n",
|
||||
"</style>\n",
|
||||
"<table border=\"1\" class=\"dataframe\">\n",
|
||||
" <thead>\n",
|
||||
" <tr style=\"text-align: right;\">\n",
|
||||
|
|
@ -928,7 +871,7 @@
|
|||
"0 1.20e+00 9.61e-03 "
|
||||
]
|
||||
},
|
||||
"execution_count": 26,
|
||||
"execution_count": 25,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
|
@ -951,26 +894,15 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 27,
|
||||
"metadata": {},
|
||||
"execution_count": 26,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<div>\n",
|
||||
"<style>\n",
|
||||
" .dataframe thead tr:only-child th {\n",
|
||||
" text-align: right;\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" .dataframe thead th {\n",
|
||||
" text-align: left;\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" .dataframe tbody tr th {\n",
|
||||
" vertical-align: top;\n",
|
||||
" }\n",
|
||||
"</style>\n",
|
||||
"<table border=\"1\" class=\"dataframe\">\n",
|
||||
" <thead>\n",
|
||||
" <tr style=\"text-align: right;\">\n",
|
||||
|
|
@ -1007,7 +939,7 @@
|
|||
"0 7.49e-01 6.09e-03 "
|
||||
]
|
||||
},
|
||||
"execution_count": 27,
|
||||
"execution_count": 26,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
|
@ -1028,26 +960,15 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 28,
|
||||
"metadata": {},
|
||||
"execution_count": 27,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<div>\n",
|
||||
"<style>\n",
|
||||
" .dataframe thead tr:only-child th {\n",
|
||||
" text-align: right;\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" .dataframe thead th {\n",
|
||||
" text-align: left;\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" .dataframe tbody tr th {\n",
|
||||
" vertical-align: top;\n",
|
||||
" }\n",
|
||||
"</style>\n",
|
||||
"<table border=\"1\" class=\"dataframe\">\n",
|
||||
" <thead>\n",
|
||||
" <tr style=\"text-align: right;\">\n",
|
||||
|
|
@ -1084,7 +1005,7 @@
|
|||
"0 1.66e+00 1.44e-02 "
|
||||
]
|
||||
},
|
||||
"execution_count": 28,
|
||||
"execution_count": 27,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
|
@ -1104,26 +1025,15 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 29,
|
||||
"metadata": {},
|
||||
"execution_count": 28,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<div>\n",
|
||||
"<style>\n",
|
||||
" .dataframe thead tr:only-child th {\n",
|
||||
" text-align: right;\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" .dataframe thead th {\n",
|
||||
" text-align: left;\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" .dataframe tbody tr th {\n",
|
||||
" vertical-align: top;\n",
|
||||
" }\n",
|
||||
"</style>\n",
|
||||
"<table border=\"1\" class=\"dataframe\">\n",
|
||||
" <thead>\n",
|
||||
" <tr style=\"text-align: right;\">\n",
|
||||
|
|
@ -1158,7 +1068,7 @@
|
|||
"0 ((absorption + current) / (absorption + current)) 9.85e-01 5.51e-03 "
|
||||
]
|
||||
},
|
||||
"execution_count": 29,
|
||||
"execution_count": 28,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
|
@ -1177,26 +1087,15 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 30,
|
||||
"metadata": {},
|
||||
"execution_count": 29,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<div>\n",
|
||||
"<style>\n",
|
||||
" .dataframe thead tr:only-child th {\n",
|
||||
" text-align: right;\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" .dataframe thead th {\n",
|
||||
" text-align: left;\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" .dataframe tbody tr th {\n",
|
||||
" vertical-align: top;\n",
|
||||
" }\n",
|
||||
"</style>\n",
|
||||
"<table border=\"1\" class=\"dataframe\">\n",
|
||||
" <thead>\n",
|
||||
" <tr style=\"text-align: right;\">\n",
|
||||
|
|
@ -1231,7 +1130,7 @@
|
|||
"0 (absorption / (absorption + current)) 9.97e-01 7.55e-03 "
|
||||
]
|
||||
},
|
||||
"execution_count": 30,
|
||||
"execution_count": 29,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
|
@ -1250,26 +1149,15 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 31,
|
||||
"metadata": {},
|
||||
"execution_count": 30,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<div>\n",
|
||||
"<style>\n",
|
||||
" .dataframe thead tr:only-child th {\n",
|
||||
" text-align: right;\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" .dataframe thead th {\n",
|
||||
" text-align: left;\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" .dataframe tbody tr th {\n",
|
||||
" vertical-align: top;\n",
|
||||
" }\n",
|
||||
"</style>\n",
|
||||
"<table border=\"1\" class=\"dataframe\">\n",
|
||||
" <thead>\n",
|
||||
" <tr style=\"text-align: right;\">\n",
|
||||
|
|
@ -1306,7 +1194,7 @@
|
|||
"0 (((((((absorption + current) / (absorption + c... 1.02e+00 1.88e-02 "
|
||||
]
|
||||
},
|
||||
"execution_count": 31,
|
||||
"execution_count": 30,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
|
@ -1327,7 +1215,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 32,
|
||||
"execution_count": 31,
|
||||
"metadata": {
|
||||
"collapsed": true,
|
||||
"scrolled": true
|
||||
|
|
@ -1343,26 +1231,15 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 33,
|
||||
"metadata": {},
|
||||
"execution_count": 32,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<div>\n",
|
||||
"<style>\n",
|
||||
" .dataframe thead tr:only-child th {\n",
|
||||
" text-align: right;\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" .dataframe thead th {\n",
|
||||
" text-align: left;\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" .dataframe tbody tr th {\n",
|
||||
" vertical-align: top;\n",
|
||||
" }\n",
|
||||
"</style>\n",
|
||||
"<table border=\"1\" class=\"dataframe\">\n",
|
||||
" <thead>\n",
|
||||
" <tr style=\"text-align: right;\">\n",
|
||||
|
|
@ -1483,7 +1360,7 @@
|
|||
"7 (scatter / flux) 3.36e-03 1.34e-05 "
|
||||
]
|
||||
},
|
||||
"execution_count": 33,
|
||||
"execution_count": 32,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
|
@ -1502,8 +1379,10 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 34,
|
||||
"metadata": {},
|
||||
"execution_count": 33,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
|
|
@ -1532,8 +1411,10 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 35,
|
||||
"metadata": {},
|
||||
"execution_count": 34,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
|
|
@ -1554,8 +1435,10 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 36,
|
||||
"metadata": {},
|
||||
"execution_count": 35,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
|
|
@ -1583,26 +1466,15 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 37,
|
||||
"metadata": {},
|
||||
"execution_count": 36,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<div>\n",
|
||||
"<style>\n",
|
||||
" .dataframe thead tr:only-child th {\n",
|
||||
" text-align: right;\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" .dataframe thead th {\n",
|
||||
" text-align: left;\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" .dataframe tbody tr th {\n",
|
||||
" vertical-align: top;\n",
|
||||
" }\n",
|
||||
"</style>\n",
|
||||
"<table border=\"1\" class=\"dataframe\">\n",
|
||||
" <thead>\n",
|
||||
" <tr style=\"text-align: right;\">\n",
|
||||
|
|
@ -1675,7 +1547,7 @@
|
|||
"3 5.98e-04 "
|
||||
]
|
||||
},
|
||||
"execution_count": 37,
|
||||
"execution_count": 36,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
|
@ -1688,26 +1560,15 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 38,
|
||||
"metadata": {},
|
||||
"execution_count": 37,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<div>\n",
|
||||
"<style>\n",
|
||||
" .dataframe thead tr:only-child th {\n",
|
||||
" text-align: right;\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" .dataframe thead th {\n",
|
||||
" text-align: left;\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" .dataframe tbody tr th {\n",
|
||||
" vertical-align: top;\n",
|
||||
" }\n",
|
||||
"</style>\n",
|
||||
"<table border=\"1\" class=\"dataframe\">\n",
|
||||
" <thead>\n",
|
||||
" <tr style=\"text-align: right;\">\n",
|
||||
|
|
@ -1840,7 +1701,7 @@
|
|||
"8 2.90e-03 "
|
||||
]
|
||||
},
|
||||
"execution_count": 38,
|
||||
"execution_count": 37,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
|
@ -1870,7 +1731,7 @@
|
|||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.6.1"
|
||||
"version": "3.6.0"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
|
|
|
|||
116
include/openmc.h
Normal file
116
include/openmc.h
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
#ifndef OPENMC_H
|
||||
#define OPENMC_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct Bank {
|
||||
double wgt;
|
||||
double xyz[3];
|
||||
double uvw[3];
|
||||
double E;
|
||||
int delayed_group;
|
||||
};
|
||||
|
||||
void openmc_calculate_voumes();
|
||||
int openmc_cell_get_fill(int32_t index, int* type, int32_t** indices, int32_t* n);
|
||||
int openmc_cell_get_id(int32_t index, int32_t* id);
|
||||
int openmc_cell_set_fill(int32_t index, int type, int32_t n, const int32_t* indices);
|
||||
int openmc_cell_set_id(int32_t index, int32_t id);
|
||||
int openmc_cell_set_temperature(int32_t index, double T, const int32_t* instance);
|
||||
int openmc_energy_filter_get_bins(int32_t index, double** energies, int32_t* n);
|
||||
int openmc_energy_filter_set_bins(int32_t index, int32_t n, const double* energies);
|
||||
int openmc_extend_cells(int32_t n, int32_t* index_start, int32_t* index_end);
|
||||
int openmc_extend_filters(int32_t n, int32_t* index_start, int32_t* index_end);
|
||||
int openmc_extend_materials(int32_t n, int32_t* index_start, int32_t* index_end);
|
||||
int openmc_extend_sources(int32_t n, int32_t* index_start, int32_t* index_end);
|
||||
int openmc_extend_tallies(int32_t n, int32_t* index_start, int32_t* index_end);
|
||||
int openmc_filter_get_id(int32_t index, int32_t* id);
|
||||
int openmc_filter_set_id(int32_t index, int32_t id);
|
||||
void openmc_finalize();
|
||||
int openmc_find(double* xyz, int rtype, int32_t* id, int32_t* instance);
|
||||
int openmc_get_cell_index(int32_t id, int32_t* index);
|
||||
int openmc_get_filter_index(int32_t id, int32_t* index);
|
||||
void openmc_get_filter_next_id(int32_t* id);
|
||||
int openmc_get_keff(double k_combined[]);
|
||||
int openmc_get_material_index(int32_t id, int32_t* index);
|
||||
int openmc_get_nuclide_index(char name[], int* index);
|
||||
int openmc_get_tally_index(int32_t id, int32_t* index);
|
||||
void openmc_hard_reset();
|
||||
void openmc_init(const int* intracomm);
|
||||
int openmc_load_nuclide(char name[]);
|
||||
int openmc_material_add_nuclide(int32_t index, const char name[], double density);
|
||||
int openmc_material_get_densities(int32_t index, int** nuclides, double** densities, int* n);
|
||||
int openmc_material_get_id(int32_t index, int32_t* id);
|
||||
int openmc_material_set_density(int32_t index, double density);
|
||||
int openmc_material_set_densities(int32_t index, int n, const char** name, const double* density);
|
||||
int openmc_material_set_id(int32_t index, int32_t id);
|
||||
int openmc_material_filter_get_bins(int32_t index, int32_t** bins, int32_t* n);
|
||||
int openmc_material_filter_set_bins(int32_t index, int32_t n, const int32_t* bins);
|
||||
int openmc_mesh_filter_set_mesh(int32_t index, int32_t index_mesh);
|
||||
int openmc_next_batch();
|
||||
int openmc_nuclide_name(int index, char** name);
|
||||
void openmc_plot_geometry();
|
||||
void openmc_reset();
|
||||
void openmc_run();
|
||||
void openmc_simulation_finalize();
|
||||
void openmc_simulation_init();
|
||||
int openmc_source_bank(struct Bank** ptr, int64_t* n);
|
||||
int openmc_source_set_strength(int32_t index, double strength);
|
||||
void openmc_statepoint_write(const char filename[]);
|
||||
int openmc_tally_get_id(int32_t index, int32_t* id);
|
||||
int openmc_tally_get_filters(int32_t index, int32_t** indices, int* n);
|
||||
int openmc_tally_get_n_realizations(int32_t index, int32_t* n);
|
||||
int openmc_tally_get_nuclides(int32_t index, int** nuclides, int* n);
|
||||
int openmc_tally_get_scores(int32_t index, int** scores, int* n);
|
||||
int openmc_tally_results(int32_t index, double** ptr, int shape_[3]);
|
||||
int openmc_tally_set_filters(int32_t index, int n, const int32_t* indices);
|
||||
int openmc_tally_set_id(int32_t index, int32_t id);
|
||||
int openmc_tally_set_nuclides(int32_t index, int n, const char** nuclides);
|
||||
int openmc_tally_set_scores(int32_t index, int n, const int* scores);
|
||||
|
||||
// Error codes
|
||||
extern int E_UNASSIGNED;
|
||||
extern int E_ALLOCATE;
|
||||
extern int E_OUT_OF_BOUNDS;
|
||||
extern int E_INVALID_SIZE;
|
||||
extern int E_INVALID_ARGUMENT;
|
||||
extern int E_INVALID_TYPE;
|
||||
extern int E_INVALID_ID;
|
||||
extern int E_GEOMETRY;
|
||||
extern int E_DATA;
|
||||
extern int E_PHYSICS;
|
||||
extern int E_WARNING;
|
||||
|
||||
// Global variables
|
||||
extern char openmc_err_msg[256];
|
||||
extern double keff;
|
||||
extern double keff_std;
|
||||
extern int32_t n_batches;
|
||||
extern int32_t n_cells;
|
||||
extern int32_t n_filters;
|
||||
extern int32_t n_inactive;
|
||||
extern int32_t n_lattices;
|
||||
extern int32_t n_materials;
|
||||
extern int32_t n_meshes;
|
||||
extern int64_t n_particles;
|
||||
extern int32_t n_plots;
|
||||
extern int32_t n_realizations;
|
||||
extern int32_t n_sab_tables;
|
||||
extern int32_t n_sources;
|
||||
extern int32_t n_surfaces;
|
||||
extern int32_t n_tallies;
|
||||
extern int32_t n_universes;
|
||||
extern int run_mode;
|
||||
extern bool simulation_initialized;
|
||||
extern int verbosity;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // OPENMC_H
|
||||
|
|
@ -59,7 +59,7 @@ Indicates the default path to a directory containing windowed multipole data if
|
|||
the user has not specified the <multipole_library> tag in
|
||||
.I materials.xml\fP.
|
||||
.SH LICENSE
|
||||
Copyright \(co 2011-2017 Massachusetts Institute of Technology.
|
||||
Copyright \(co 2011-2018 Massachusetts Institute of Technology.
|
||||
.PP
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
|
|
|
|||
|
|
@ -27,5 +27,9 @@ from openmc.particle_restart import *
|
|||
from openmc.mixin import *
|
||||
from openmc.plotter import *
|
||||
from openmc.search import *
|
||||
from . import examples
|
||||
|
||||
__version__ = '0.9.0'
|
||||
# Import a few convencience functions that used to be here
|
||||
from openmc.model import get_rectangular_prism, get_hexagonal_prism
|
||||
|
||||
__version__ = '0.10.0'
|
||||
|
|
|
|||
49
openmc/_utils.py
Normal file
49
openmc/_utils.py
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
import os.path
|
||||
from pathlib import Path
|
||||
from urllib.parse import urlparse
|
||||
from urllib.request import urlopen
|
||||
|
||||
_BLOCK_SIZE = 16384
|
||||
|
||||
|
||||
def download(url):
|
||||
"""Download file from a URL
|
||||
|
||||
Parameters
|
||||
----------
|
||||
url : str
|
||||
URL from which to download
|
||||
|
||||
Returns
|
||||
-------
|
||||
basename : str
|
||||
Name of file written locally
|
||||
|
||||
"""
|
||||
req = urlopen(url)
|
||||
|
||||
# Get file size from header
|
||||
file_size = req.length
|
||||
|
||||
# Check if file already downloaded
|
||||
basename = Path(urlparse(url).path).name
|
||||
if os.path.exists(basename):
|
||||
if os.path.getsize(basename) == file_size:
|
||||
print('Skipping {}, already downloaded'.format(basename))
|
||||
return basename
|
||||
|
||||
# Copy file to disk in chunks
|
||||
print('Downloading {}... '.format(basename), end='')
|
||||
downloaded = 0
|
||||
with open(basename, 'wb') as fh:
|
||||
while True:
|
||||
chunk = req.read(_BLOCK_SIZE)
|
||||
if not chunk:
|
||||
break
|
||||
fh.write(chunk)
|
||||
downloaded += len(chunk)
|
||||
status = '{:10} [{:3.2f}%]'.format(
|
||||
downloaded, downloaded * 100. / file_size)
|
||||
print(status + '\b'*len(status), end='')
|
||||
print('')
|
||||
return basename
|
||||
|
|
@ -2,7 +2,6 @@ import sys
|
|||
import copy
|
||||
from collections import Iterable
|
||||
|
||||
from six import string_types
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
|
||||
|
|
@ -86,18 +85,18 @@ class CrossScore(object):
|
|||
@left_score.setter
|
||||
def left_score(self, left_score):
|
||||
cv.check_type('left_score', left_score,
|
||||
string_types + (CrossScore, AggregateScore))
|
||||
(str, CrossScore, AggregateScore))
|
||||
self._left_score = left_score
|
||||
|
||||
@right_score.setter
|
||||
def right_score(self, right_score):
|
||||
cv.check_type('right_score', right_score,
|
||||
string_types + (CrossScore, AggregateScore))
|
||||
(str, CrossScore, AggregateScore))
|
||||
self._right_score = right_score
|
||||
|
||||
@binary_op.setter
|
||||
def binary_op(self, binary_op):
|
||||
cv.check_type('binary_op', binary_op, string_types)
|
||||
cv.check_type('binary_op', binary_op, str)
|
||||
cv.check_value('binary_op', binary_op, _TALLY_ARITHMETIC_OPS)
|
||||
self._binary_op = binary_op
|
||||
|
||||
|
|
@ -202,7 +201,7 @@ class CrossNuclide(object):
|
|||
|
||||
@binary_op.setter
|
||||
def binary_op(self, binary_op):
|
||||
cv.check_type('binary_op', binary_op, string_types)
|
||||
cv.check_type('binary_op', binary_op, str)
|
||||
cv.check_value('binary_op', binary_op, _TALLY_ARITHMETIC_OPS)
|
||||
self._binary_op = binary_op
|
||||
|
||||
|
|
@ -237,9 +236,6 @@ class CrossFilter(object):
|
|||
left / right filters
|
||||
num_bins : Integral
|
||||
The number of filter bins (always 1 if aggregate_filter is defined)
|
||||
stride : Integral
|
||||
The number of filter, nuclide and score bins within each of this
|
||||
crossfilter's bins.
|
||||
|
||||
"""
|
||||
|
||||
|
|
@ -250,7 +246,6 @@ class CrossFilter(object):
|
|||
self._type = '({0} {1} {2})'.format(left_type, binary_op, right_type)
|
||||
|
||||
self._bins = {}
|
||||
self._stride = None
|
||||
|
||||
self._left_filter = None
|
||||
self._right_filter = None
|
||||
|
|
@ -314,10 +309,6 @@ class CrossFilter(object):
|
|||
else:
|
||||
return 0
|
||||
|
||||
@property
|
||||
def stride(self):
|
||||
return self._stride
|
||||
|
||||
@type.setter
|
||||
def type(self, filter_type):
|
||||
if filter_type not in _FILTER_TYPES:
|
||||
|
|
@ -343,14 +334,10 @@ class CrossFilter(object):
|
|||
|
||||
@binary_op.setter
|
||||
def binary_op(self, binary_op):
|
||||
cv.check_type('binary_op', binary_op, string_types)
|
||||
cv.check_type('binary_op', binary_op, str)
|
||||
cv.check_value('binary_op', binary_op, _TALLY_ARITHMETIC_OPS)
|
||||
self._binary_op = binary_op
|
||||
|
||||
@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.
|
||||
|
||||
|
|
@ -494,12 +481,12 @@ class AggregateScore(object):
|
|||
|
||||
@scores.setter
|
||||
def scores(self, scores):
|
||||
cv.check_iterable_type('scores', scores, string_types)
|
||||
cv.check_iterable_type('scores', scores, str)
|
||||
self._scores = scores
|
||||
|
||||
@aggregate_op.setter
|
||||
def aggregate_op(self, aggregate_op):
|
||||
cv.check_type('aggregate_op', aggregate_op, string_types +(CrossScore,))
|
||||
cv.check_type('aggregate_op', aggregate_op, (str, CrossScore))
|
||||
cv.check_value('aggregate_op', aggregate_op, _TALLY_AGGREGATE_OPS)
|
||||
self._aggregate_op = aggregate_op
|
||||
|
||||
|
|
@ -573,13 +560,12 @@ class AggregateNuclide(object):
|
|||
|
||||
@nuclides.setter
|
||||
def nuclides(self, nuclides):
|
||||
cv.check_iterable_type('nuclides', nuclides,
|
||||
string_types + (openmc.Nuclide, CrossNuclide))
|
||||
cv.check_iterable_type('nuclides', nuclides, (str, CrossNuclide))
|
||||
self._nuclides = nuclides
|
||||
|
||||
@aggregate_op.setter
|
||||
def aggregate_op(self, aggregate_op):
|
||||
cv.check_type('aggregate_op', aggregate_op, string_types)
|
||||
cv.check_type('aggregate_op', aggregate_op, str)
|
||||
cv.check_value('aggregate_op', aggregate_op, _TALLY_AGGREGATE_OPS)
|
||||
self._aggregate_op = aggregate_op
|
||||
|
||||
|
|
@ -611,9 +597,6 @@ class AggregateFilter(object):
|
|||
The filter bins included in the aggregation
|
||||
num_bins : Integral
|
||||
The number of filter bins (always 1 if aggregate_filter is defined)
|
||||
stride : Integral
|
||||
The number of filter, nuclide and score bins within each of this
|
||||
aggregatefilter's bins.
|
||||
|
||||
"""
|
||||
|
||||
|
|
@ -622,7 +605,6 @@ class AggregateFilter(object):
|
|||
self._type = '{0}({1})'.format(aggregate_op,
|
||||
aggregate_filter.short_name.lower())
|
||||
self._bins = None
|
||||
self._stride = None
|
||||
|
||||
self._aggregate_filter = None
|
||||
self._aggregate_op = None
|
||||
|
|
@ -684,10 +666,6 @@ class AggregateFilter(object):
|
|||
def num_bins(self):
|
||||
return len(self.bins) if self.aggregate_filter else 0
|
||||
|
||||
@property
|
||||
def stride(self):
|
||||
return self._stride
|
||||
|
||||
@type.setter
|
||||
def type(self, filter_type):
|
||||
if filter_type not in _FILTER_TYPES:
|
||||
|
|
@ -710,14 +688,10 @@ class AggregateFilter(object):
|
|||
|
||||
@aggregate_op.setter
|
||||
def aggregate_op(self, aggregate_op):
|
||||
cv.check_type('aggregate_op', aggregate_op, string_types)
|
||||
cv.check_type('aggregate_op', aggregate_op, str)
|
||||
cv.check_value('aggregate_op', aggregate_op, _TALLY_AGGREGATE_OPS)
|
||||
self._aggregate_op = aggregate_op
|
||||
|
||||
@stride.setter
|
||||
def stride(self, stride):
|
||||
self._stride = stride
|
||||
|
||||
def get_bin_index(self, filter_bin):
|
||||
"""Returns the index in the AggregateFilter for some bin.
|
||||
|
||||
|
|
@ -753,7 +727,7 @@ class AggregateFilter(object):
|
|||
else:
|
||||
return self.bins.index(filter_bin)
|
||||
|
||||
def get_pandas_dataframe(self, data_size, summary=None, **kwargs):
|
||||
def get_pandas_dataframe(self, data_size, stride, summary=None, **kwargs):
|
||||
"""Builds a Pandas DataFrame for the AggregateFilter's bins.
|
||||
|
||||
This method constructs a Pandas DataFrame object for the AggregateFilter
|
||||
|
|
@ -762,8 +736,10 @@ class AggregateFilter(object):
|
|||
|
||||
Parameters
|
||||
----------
|
||||
data_size : Integral
|
||||
data_size : int
|
||||
The total number of bins in the tally corresponding to this filter
|
||||
stride : int
|
||||
Stride in memory for the filter
|
||||
summary : None or Summary
|
||||
An optional Summary object to be used to construct columns for
|
||||
distribcell tally filters (default is None). NOTE: This parameter
|
||||
|
|
@ -793,7 +769,7 @@ class AggregateFilter(object):
|
|||
filter_bins[i] = bin
|
||||
|
||||
# Repeat and tile bins as needed for DataFrame
|
||||
filter_bins = np.repeat(filter_bins, self.stride)
|
||||
filter_bins = np.repeat(filter_bins, stride)
|
||||
tile_factor = data_size / len(filter_bins)
|
||||
filter_bins = np.tile(filter_bins, tile_factor)
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ objects in the :mod:`openmc.capi` subpackage, for example:
|
|||
from ctypes import CDLL
|
||||
import os
|
||||
import sys
|
||||
from warnings import warn
|
||||
|
||||
import pkg_resources
|
||||
|
||||
|
|
@ -36,10 +35,7 @@ else:
|
|||
# available. Instead, we create a mock object so that when the modules
|
||||
# within the openmc.capi package try to configure arguments and return
|
||||
# values for symbols, no errors occur
|
||||
try:
|
||||
from unittest.mock import Mock
|
||||
except ImportError:
|
||||
from mock import Mock
|
||||
from unittest.mock import Mock
|
||||
_dll = Mock()
|
||||
|
||||
from .error import *
|
||||
|
|
@ -50,6 +46,3 @@ from .cell import *
|
|||
from .filter import *
|
||||
from .tally import *
|
||||
from .settings import settings
|
||||
|
||||
warn("The Python bindings to OpenMC's C API are still unstable "
|
||||
"and may change substantially in future releases.", FutureWarning)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from collections import Mapping, Iterable
|
||||
from collections.abc import Mapping, Iterable
|
||||
from ctypes import c_int, c_int32, c_double, c_char_p, POINTER
|
||||
from weakref import WeakValueDictionary
|
||||
|
||||
|
|
@ -7,21 +7,29 @@ from numpy.ctypeslib import as_array
|
|||
|
||||
from . import _dll
|
||||
from .core import _FortranObjectWithID
|
||||
from .error import _error_handler
|
||||
from .error import _error_handler, AllocationError, InvalidIDError
|
||||
from .material import Material
|
||||
|
||||
__all__ = ['Cell', 'cells']
|
||||
|
||||
# Cell functions
|
||||
_dll.openmc_extend_cells.argtypes = [c_int32, POINTER(c_int32), POINTER(c_int32)]
|
||||
_dll.openmc_extend_cells.restype = c_int
|
||||
_dll.openmc_extend_cells.errcheck = _error_handler
|
||||
_dll.openmc_cell_get_id.argtypes = [c_int32, POINTER(c_int32)]
|
||||
_dll.openmc_cell_get_id.restype = c_int
|
||||
_dll.openmc_cell_get_id.errcheck = _error_handler
|
||||
_dll.openmc_cell_get_fill.argtypes = [
|
||||
c_int32, POINTER(c_int), POINTER(POINTER(c_int32)), POINTER(c_int32)]
|
||||
_dll.openmc_cell_get_fill.restype = c_int
|
||||
_dll.openmc_cell_get_fill.errcheck = _error_handler
|
||||
_dll.openmc_cell_set_fill.argtypes = [
|
||||
c_int32, c_int, c_int32, POINTER(c_int32)]
|
||||
_dll.openmc_cell_set_fill.restype = c_int
|
||||
_dll.openmc_cell_set_fill.errcheck = _error_handler
|
||||
_dll.openmc_cell_set_id.argtypes = [c_int32, c_int32]
|
||||
_dll.openmc_cell_set_id.restype = c_int
|
||||
_dll.openmc_cell_set_id.errcheck = _error_handler
|
||||
_dll.openmc_cell_set_temperature.argtypes = [
|
||||
c_int32, c_double, POINTER(c_int32)]
|
||||
_dll.openmc_cell_set_temperature.restype = c_int
|
||||
|
|
@ -51,11 +59,32 @@ class Cell(_FortranObjectWithID):
|
|||
"""
|
||||
__instances = WeakValueDictionary()
|
||||
|
||||
def __new__(cls, *args):
|
||||
if args not in cls.__instances:
|
||||
instance = super(Cell, self).__new__(cls)
|
||||
cls.__instances[args] = instance
|
||||
return cls.__instances[args]
|
||||
def __new__(cls, uid=None, new=True, index=None):
|
||||
mapping = cells
|
||||
if index is None:
|
||||
if new:
|
||||
# Determine ID to assign
|
||||
if uid is None:
|
||||
uid = max(mapping, default=0) + 1
|
||||
else:
|
||||
if uid in mapping:
|
||||
raise AllocationError('A cell with ID={} has already '
|
||||
'been allocated.'.format(uid))
|
||||
|
||||
index = c_int32()
|
||||
_dll.openmc_extend_cells(1, index, None)
|
||||
index = index.value
|
||||
else:
|
||||
index = mapping[uid]._index
|
||||
|
||||
if index not in cls.__instances:
|
||||
instance = super().__new__(cls)
|
||||
instance._index = index
|
||||
if uid is not None:
|
||||
instance.id = uid
|
||||
cls.__instances[index] = instance
|
||||
|
||||
return cls.__instances[index]
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
|
|
@ -63,6 +92,10 @@ class Cell(_FortranObjectWithID):
|
|||
_dll.openmc_cell_get_id(self._index, cell_id)
|
||||
return cell_id.value
|
||||
|
||||
@id.setter
|
||||
def id(self, cell_id):
|
||||
_dll.openmc_cell_set_id(self._index, cell_id)
|
||||
|
||||
@property
|
||||
def fill(self):
|
||||
fill_type = c_int()
|
||||
|
|
@ -113,11 +146,11 @@ class _CellMapping(Mapping):
|
|||
except (AllocationError, InvalidIDError) as e:
|
||||
# __contains__ expects a KeyError to work correctly
|
||||
raise KeyError(str(e))
|
||||
return Cell(index.value)
|
||||
return Cell(index=index.value)
|
||||
|
||||
def __iter__(self):
|
||||
for i in range(len(self)):
|
||||
yield Cell(i + 1).id
|
||||
yield Cell(index=i + 1).id
|
||||
|
||||
def __len__(self):
|
||||
return c_int32.in_dll(_dll, 'n_cells').value
|
||||
|
|
|
|||
|
|
@ -1,9 +1,22 @@
|
|||
from contextlib import contextmanager
|
||||
from ctypes import CDLL, c_int, c_int32, c_double, POINTER
|
||||
from ctypes import (CDLL, c_int, c_int32, c_int64, c_double, c_char_p,
|
||||
POINTER, Structure)
|
||||
from warnings import warn
|
||||
|
||||
import numpy as np
|
||||
from numpy.ctypeslib import as_array
|
||||
|
||||
from . import _dll
|
||||
from .error import _error_handler
|
||||
from .error import _error_handler, AllocationError
|
||||
import openmc.capi
|
||||
|
||||
|
||||
class _Bank(Structure):
|
||||
_fields_ = [('wgt', c_double),
|
||||
('xyz', c_double*3),
|
||||
('uvw', c_double*3),
|
||||
('E', c_double),
|
||||
('delayed_group', c_int)]
|
||||
|
||||
|
||||
_dll.openmc_calculate_volumes.restype = None
|
||||
|
|
@ -18,9 +31,17 @@ _dll.openmc_init.restype = None
|
|||
_dll.openmc_get_keff.argtypes = [POINTER(c_double*2)]
|
||||
_dll.openmc_get_keff.restype = c_int
|
||||
_dll.openmc_get_keff.errcheck = _error_handler
|
||||
_dll.openmc_next_batch.restype = c_int
|
||||
_dll.openmc_plot_geometry.restype = None
|
||||
_dll.openmc_run.restype = None
|
||||
_dll.openmc_reset.restype = None
|
||||
_dll.openmc_source_bank.argtypes = [POINTER(POINTER(_Bank)), POINTER(c_int64)]
|
||||
_dll.openmc_source_bank.restype = c_int
|
||||
_dll.openmc_source_bank.errcheck = _error_handler
|
||||
_dll.openmc_simulation_init.restype = None
|
||||
_dll.openmc_simulation_finalize.restype = None
|
||||
_dll.openmc_statepoint_write.argtypes = [POINTER(c_char_p)]
|
||||
_dll.openmc_statepoint_write.restype = None
|
||||
|
||||
|
||||
def calculate_volumes():
|
||||
|
|
@ -43,8 +64,8 @@ def find_cell(xyz):
|
|||
|
||||
Returns
|
||||
-------
|
||||
int
|
||||
ID of the cell.
|
||||
openmc.capi.Cell
|
||||
Cell containing the point
|
||||
int
|
||||
If the cell at the given point is repeated in the geometry, this
|
||||
indicates which instance it is, i.e., 0 would be the first instance.
|
||||
|
|
@ -53,7 +74,7 @@ def find_cell(xyz):
|
|||
uid = c_int32()
|
||||
instance = c_int32()
|
||||
_dll.openmc_find((c_double*3)(*xyz), 1, uid, instance)
|
||||
return uid.value, instance.value
|
||||
return openmc.capi.cells[uid.value], instance.value
|
||||
|
||||
|
||||
def find_material(xyz):
|
||||
|
|
@ -66,14 +87,14 @@ def find_material(xyz):
|
|||
|
||||
Returns
|
||||
-------
|
||||
int or None
|
||||
ID of the material or None is no material is found
|
||||
openmc.capi.Material or None
|
||||
Material containing the point, or None is no material is found
|
||||
|
||||
"""
|
||||
uid = c_int32()
|
||||
instance = c_int32()
|
||||
_dll.openmc_find((c_double*3)(*xyz), 2, uid, instance)
|
||||
return uid.value if uid != 0 else None
|
||||
return openmc.capi.materials[uid.value] if uid != 0 else None
|
||||
|
||||
|
||||
def hard_reset():
|
||||
|
|
@ -102,6 +123,40 @@ def init(intracomm=None):
|
|||
_dll.openmc_init(None)
|
||||
|
||||
|
||||
def iter_batches():
|
||||
"""Iterator over batches.
|
||||
|
||||
This function returns a generator-iterator that allows Python code to be run
|
||||
between batches in an OpenMC simulation. It should be used in conjunction
|
||||
with :func:`openmc.capi.simulation_init` and
|
||||
:func:`openmc.capi.simulation_finalize`. For example:
|
||||
|
||||
.. code-block:: Python
|
||||
|
||||
with openmc.capi.run_in_memory():
|
||||
openmc.capi.simulation_init()
|
||||
for _ in openmc.capi.iter_batches():
|
||||
# Look at convergence of tallies, for example
|
||||
...
|
||||
openmc.capi.simulation_finalize()
|
||||
|
||||
See Also
|
||||
--------
|
||||
openmc.capi.next_batch
|
||||
|
||||
"""
|
||||
while True:
|
||||
# Run next batch
|
||||
retval = next_batch()
|
||||
|
||||
# Provide opportunity for user to perform action between batches
|
||||
yield
|
||||
|
||||
# End the iteration
|
||||
if retval < 0:
|
||||
break
|
||||
|
||||
|
||||
def keff():
|
||||
"""Return the calculated k-eigenvalue and its standard deviation.
|
||||
|
||||
|
|
@ -111,9 +166,26 @@ def keff():
|
|||
Mean k-eigenvalue and standard deviation of the mean
|
||||
|
||||
"""
|
||||
k = (c_double*2)()
|
||||
_dll.openmc_get_keff(k)
|
||||
return tuple(k)
|
||||
n = openmc.capi.num_realizations()
|
||||
if n > 3:
|
||||
# Use the combined estimator if there are enough realizations
|
||||
k = (c_double*2)()
|
||||
_dll.openmc_get_keff(k)
|
||||
return tuple(k)
|
||||
else:
|
||||
# Otherwise, return the tracklength estimator
|
||||
mean = c_double.in_dll(_dll, 'keff').value
|
||||
std_dev = c_double.in_dll(_dll, 'keff_std').value if n > 1 else np.inf
|
||||
return (mean, std_dev)
|
||||
|
||||
|
||||
def next_batch():
|
||||
"""Run next batch."""
|
||||
retval = _dll.openmc_next_batch()
|
||||
if retval == -3:
|
||||
raise AllocationError('Simulation has not been initialized. You must call '
|
||||
'openmc.capi.simulation_init() first.')
|
||||
return retval
|
||||
|
||||
|
||||
def plot_geometry():
|
||||
|
|
@ -131,6 +203,50 @@ def run():
|
|||
_dll.openmc_run()
|
||||
|
||||
|
||||
def simulation_init():
|
||||
"""Initialize simulation"""
|
||||
_dll.openmc_simulation_init()
|
||||
|
||||
|
||||
def simulation_finalize():
|
||||
"""Finalize simulation"""
|
||||
_dll.openmc_simulation_finalize()
|
||||
|
||||
|
||||
def source_bank():
|
||||
"""Return source bank as NumPy array
|
||||
|
||||
Returns
|
||||
-------
|
||||
numpy.ndarray
|
||||
Source sites
|
||||
|
||||
"""
|
||||
# Get pointer to source bank
|
||||
ptr = POINTER(_Bank)()
|
||||
n = c_int64()
|
||||
_dll.openmc_source_bank(ptr, n)
|
||||
|
||||
# Convert to numpy array with appropriate datatype
|
||||
bank_dtype = np.dtype(_Bank)
|
||||
return as_array(ptr, (n.value,)).view(bank_dtype)
|
||||
|
||||
|
||||
def statepoint_write(filename=None):
|
||||
"""Write a statepoint file.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
filename : str or None
|
||||
Path to the statepoint to write. If None is passed, a default name that
|
||||
contains the current batch will be written.
|
||||
|
||||
"""
|
||||
if filename is not None:
|
||||
filename = c_char_p(filename.encode())
|
||||
_dll.openmc_statepoint_write(filename)
|
||||
|
||||
|
||||
@contextmanager
|
||||
def run_in_memory(intracomm=None):
|
||||
"""Provides context manager for calling OpenMC shared library functions.
|
||||
|
|
|
|||
|
|
@ -1,41 +1,42 @@
|
|||
from ctypes import c_int, c_char
|
||||
from warnings import warn
|
||||
|
||||
from . import _dll
|
||||
|
||||
|
||||
class Error(Exception):
|
||||
class OpenMCError(Exception):
|
||||
"""Root exception class for OpenMC."""
|
||||
|
||||
|
||||
class GeometryError(Error):
|
||||
class GeometryError(OpenMCError):
|
||||
"""Geometry-related error"""
|
||||
|
||||
|
||||
class InvalidIDError(Error):
|
||||
class InvalidIDError(OpenMCError):
|
||||
"""Use of an ID that is invalid."""
|
||||
|
||||
|
||||
class AllocationError(Error):
|
||||
class AllocationError(OpenMCError):
|
||||
"""Error related to memory allocation."""
|
||||
|
||||
|
||||
class OutOfBoundsError(Error):
|
||||
class OutOfBoundsError(OpenMCError):
|
||||
"""Index in array out of bounds."""
|
||||
|
||||
|
||||
class DataError(Error):
|
||||
class DataError(OpenMCError):
|
||||
"""Error relating to nuclear data."""
|
||||
|
||||
|
||||
class PhysicsError(Error):
|
||||
class PhysicsError(OpenMCError):
|
||||
"""Error relating to performing physics."""
|
||||
|
||||
|
||||
class InvalidArgumentError(Error):
|
||||
class InvalidArgumentError(OpenMCError):
|
||||
"""Argument passed was invalid."""
|
||||
|
||||
|
||||
class InvalidTypeError(Error):
|
||||
class InvalidTypeError(OpenMCError):
|
||||
"""Tried to perform an operation on the wrong type."""
|
||||
|
||||
|
||||
|
|
@ -70,4 +71,4 @@ def _error_handler(err, func, args):
|
|||
elif err == errcode('e_warning'):
|
||||
warn(msg)
|
||||
elif err < 0:
|
||||
raise Exception("Unknown error encountered (code {}).".format(err))
|
||||
raise OpenMCError("Unknown error encountered (code {}).".format(err))
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from collections import Mapping
|
||||
from collections.abc import Mapping
|
||||
from ctypes import c_int, c_int32, c_double, c_char_p, POINTER, \
|
||||
create_string_buffer
|
||||
from weakref import WeakValueDictionary
|
||||
|
|
@ -66,10 +66,7 @@ class Filter(_FortranObjectWithID):
|
|||
if new:
|
||||
# Determine ID to assign
|
||||
if uid is None:
|
||||
try:
|
||||
uid = max(mapping) + 1
|
||||
except ValueError:
|
||||
uid = 1
|
||||
uid = max(mapping, default=0) + 1
|
||||
else:
|
||||
if uid in mapping:
|
||||
raise AllocationError('A filter with ID={} has already '
|
||||
|
|
@ -87,7 +84,7 @@ class Filter(_FortranObjectWithID):
|
|||
index = mapping[uid]._index
|
||||
|
||||
if index not in cls.__instances:
|
||||
instance = super(Filter, cls).__new__(cls)
|
||||
instance = super().__new__(cls)
|
||||
instance._index = index
|
||||
if uid is not None:
|
||||
instance.id = uid
|
||||
|
|
@ -110,7 +107,7 @@ class EnergyFilter(Filter):
|
|||
filter_type = 'energy'
|
||||
|
||||
def __init__(self, bins=None, uid=None, new=True, index=None):
|
||||
super(EnergyFilter, self).__init__(uid, new, index)
|
||||
super().__init__(uid, new, index)
|
||||
if bins is not None:
|
||||
self.bins = bins
|
||||
|
||||
|
|
@ -167,7 +164,7 @@ class MaterialFilter(Filter):
|
|||
filter_type = 'material'
|
||||
|
||||
def __init__(self, bins=None, uid=None, new=True, index=None):
|
||||
super(MaterialFilter, self).__init__(uid, new, index)
|
||||
super().__init__(uid, new, index)
|
||||
if bins is not None:
|
||||
self.bins = bins
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from collections import Mapping
|
||||
from collections.abc import Mapping
|
||||
from ctypes import c_int, c_int32, c_double, c_char_p, POINTER
|
||||
from weakref import WeakValueDictionary
|
||||
|
||||
|
|
@ -78,10 +78,7 @@ class Material(_FortranObjectWithID):
|
|||
if new:
|
||||
# Determine ID to assign
|
||||
if uid is None:
|
||||
try:
|
||||
uid = max(mapping) + 1
|
||||
except ValueError:
|
||||
uid = 1
|
||||
uid = max(mapping, default=0) + 1
|
||||
else:
|
||||
if uid in mapping:
|
||||
raise AllocationError('A material with ID={} has already '
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from collections import Mapping
|
||||
from collections.abc import Mapping
|
||||
from ctypes import c_int, c_char_p, POINTER
|
||||
from weakref import WeakValueDictionary
|
||||
|
||||
|
|
@ -58,7 +58,7 @@ class Nuclide(_FortranObject):
|
|||
|
||||
def __new__(cls, *args):
|
||||
if args not in cls.__instances:
|
||||
instance = super(Nuclide, cls).__new__(cls)
|
||||
instance = super().__new__(cls)
|
||||
cls.__instances[args] = instance
|
||||
return cls.__instances[args]
|
||||
|
||||
|
|
|
|||
|
|
@ -11,8 +11,7 @@ _RUN_MODES = {1: 'fixed source',
|
|||
5: 'volume'}
|
||||
|
||||
_dll.openmc_set_seed.argtypes = [c_int64]
|
||||
_dll.openmc_set_seed.restype = c_int
|
||||
_dll.openmc_set_seed.errcheck = _error_handler
|
||||
_dll.openmc_get_seed.restype = c_int64
|
||||
|
||||
|
||||
class _Settings(object):
|
||||
|
|
@ -43,7 +42,7 @@ class _Settings(object):
|
|||
|
||||
@property
|
||||
def seed(self):
|
||||
return c_int64.in_dll(_dll, 'seed').value
|
||||
return _dll.openmc_get_seed()
|
||||
|
||||
@seed.setter
|
||||
def seed(self, seed):
|
||||
|
|
|
|||
|
|
@ -1,24 +1,30 @@
|
|||
from collections import Mapping
|
||||
from collections.abc import Mapping
|
||||
from ctypes import c_int, c_int32, c_double, c_char_p, POINTER
|
||||
from weakref import WeakValueDictionary
|
||||
|
||||
import numpy as np
|
||||
from numpy.ctypeslib import as_array
|
||||
import scipy.stats
|
||||
|
||||
from openmc.data.reaction import REACTION_NAME
|
||||
from . import _dll, Nuclide
|
||||
from .core import _FortranObjectWithID
|
||||
from .error import _error_handler, AllocationError, InvalidIDError
|
||||
from .filter import _get_filter
|
||||
|
||||
|
||||
__all__ = ['Tally', 'tallies']
|
||||
__all__ = ['Tally', 'tallies', 'global_tallies', 'num_realizations']
|
||||
|
||||
# Tally functions
|
||||
_dll.openmc_get_tally_index.argtypes = [c_int32, POINTER(c_int32)]
|
||||
_dll.openmc_get_tally_index.restype = c_int
|
||||
_dll.openmc_get_tally_index.errcheck = _error_handler
|
||||
_dll.openmc_extend_tallies.argtypes = [c_int32, POINTER(c_int32), POINTER(c_int32)]
|
||||
_dll.openmc_extend_tallies.restype = c_int
|
||||
_dll.openmc_extend_tallies.errcheck = _error_handler
|
||||
_dll.openmc_get_tally_index.argtypes = [c_int32, POINTER(c_int32)]
|
||||
_dll.openmc_get_tally_index.restype = c_int
|
||||
_dll.openmc_get_tally_index.errcheck = _error_handler
|
||||
_dll.openmc_global_tallies.argtypes = [POINTER(POINTER(c_double))]
|
||||
_dll.openmc_global_tallies.restype = c_int
|
||||
_dll.openmc_global_tallies.errcheck = _error_handler
|
||||
_dll.openmc_tally_get_id.argtypes = [c_int32, POINTER(c_int32)]
|
||||
_dll.openmc_tally_get_id.restype = c_int
|
||||
_dll.openmc_tally_get_id.errcheck = _error_handler
|
||||
|
|
@ -26,10 +32,17 @@ _dll.openmc_tally_get_filters.argtypes = [
|
|||
c_int32, POINTER(POINTER(c_int32)), POINTER(c_int)]
|
||||
_dll.openmc_tally_get_filters.restype = c_int
|
||||
_dll.openmc_tally_get_filters.errcheck = _error_handler
|
||||
_dll.openmc_tally_get_n_realizations.argtypes = [c_int32, POINTER(c_int32)]
|
||||
_dll.openmc_tally_get_n_realizations.restype = c_int
|
||||
_dll.openmc_tally_get_n_realizations.errcheck = _error_handler
|
||||
_dll.openmc_tally_get_nuclides.argtypes = [
|
||||
c_int32, POINTER(POINTER(c_int)), POINTER(c_int)]
|
||||
_dll.openmc_tally_get_nuclides.restype = c_int
|
||||
_dll.openmc_tally_get_nuclides.errcheck = _error_handler
|
||||
_dll.openmc_tally_get_scores.argtypes = [
|
||||
c_int32, POINTER(POINTER(c_int)), POINTER(c_int)]
|
||||
_dll.openmc_tally_get_scores.restype = c_int
|
||||
_dll.openmc_tally_get_scores.errcheck = _error_handler
|
||||
_dll.openmc_tally_results.argtypes = [
|
||||
c_int32, POINTER(POINTER(c_double)), POINTER(c_int*3)]
|
||||
_dll.openmc_tally_results.restype = c_int
|
||||
|
|
@ -51,6 +64,54 @@ _dll.openmc_tally_set_type.restype = c_int
|
|||
_dll.openmc_tally_set_type.errcheck = _error_handler
|
||||
|
||||
|
||||
_SCORES = {
|
||||
-1: 'flux', -2: 'total', -3: 'scatter', -4: 'nu-scatter',
|
||||
-9: 'absorption', -10: 'fission', -11: 'nu-fission', -12: 'kappa-fission',
|
||||
-13: 'current', -18: 'events', -19: 'delayed-nu-fission',
|
||||
-20: 'prompt-nu-fission', -21: 'inverse-velocity', -22: 'fission-q-prompt',
|
||||
-23: 'fission-q-recoverable', -24: 'decay-rate'
|
||||
}
|
||||
|
||||
|
||||
def global_tallies():
|
||||
"""Mean and standard deviation of the mean for each global tally.
|
||||
|
||||
Returns
|
||||
-------
|
||||
list of tuple
|
||||
For each global tally, a tuple of (mean, standard deviation)
|
||||
|
||||
"""
|
||||
ptr = POINTER(c_double)()
|
||||
_dll.openmc_global_tallies(ptr)
|
||||
array = as_array(ptr, (4, 3))
|
||||
|
||||
# Get sum, sum-of-squares, and number of realizations
|
||||
sum_ = array[:, 1]
|
||||
sum_sq = array[:, 2]
|
||||
n = num_realizations()
|
||||
|
||||
# Determine mean
|
||||
if n > 0:
|
||||
mean = sum_ / n
|
||||
else:
|
||||
mean = sum_.copy()
|
||||
|
||||
# Determine standard deviation
|
||||
nonzero = np.abs(mean) > 0
|
||||
stdev = np.empty_like(mean)
|
||||
stdev.fill(np.inf)
|
||||
if n > 1:
|
||||
stdev[nonzero] = np.sqrt((sum_sq[nonzero]/n - mean[nonzero]**2)/(n - 1))
|
||||
|
||||
return list(zip(mean, stdev))
|
||||
|
||||
|
||||
def num_realizations():
|
||||
"""Number of realizations of global tallies."""
|
||||
return c_int32.in_dll(_dll, 'n_realizations').value
|
||||
|
||||
|
||||
class Tally(_FortranObjectWithID):
|
||||
"""Tally stored internally.
|
||||
|
||||
|
|
@ -74,10 +135,16 @@ class Tally(_FortranObjectWithID):
|
|||
ID of the tally
|
||||
filters : list
|
||||
List of tally filters
|
||||
mean : numpy.ndarray
|
||||
An array containing the sample mean for each bin
|
||||
nuclides : list of str
|
||||
List of nuclides to score results for
|
||||
num_realizations : int
|
||||
Number of realizations
|
||||
results : numpy.ndarray
|
||||
Array of tally results
|
||||
std_dev : numpy.ndarray
|
||||
An array containing the sample standard deviation for each bin
|
||||
|
||||
"""
|
||||
__instances = WeakValueDictionary()
|
||||
|
|
@ -88,10 +155,7 @@ class Tally(_FortranObjectWithID):
|
|||
if new:
|
||||
# Determine ID to assign
|
||||
if uid is None:
|
||||
try:
|
||||
uid = max(mapping) + 1
|
||||
except ValueError:
|
||||
uid = 1
|
||||
uid = max(mapping, default=0) + 1
|
||||
else:
|
||||
if uid in mapping:
|
||||
raise AllocationError('A tally with ID={} has already '
|
||||
|
|
@ -105,7 +169,7 @@ class Tally(_FortranObjectWithID):
|
|||
index = mapping[uid]._index
|
||||
|
||||
if index not in cls.__instances:
|
||||
instance = super(Tally, cls).__new__(cls)
|
||||
instance = super().__new__(cls)
|
||||
instance._index = index
|
||||
if uid is not None:
|
||||
instance.id = uid
|
||||
|
|
@ -130,21 +194,6 @@ class Tally(_FortranObjectWithID):
|
|||
_dll.openmc_tally_get_filters(self._index, filt_idx, n)
|
||||
return [_get_filter(filt_idx[i]) for i in range(n.value)]
|
||||
|
||||
@property
|
||||
def nuclides(self):
|
||||
nucs = POINTER(c_int)()
|
||||
n = c_int()
|
||||
_dll.openmc_tally_get_nuclides(self._index, nucs, n)
|
||||
return [Nuclide(nucs[i]).name if nucs[i] > 0 else 'total'
|
||||
for i in range(n.value)]
|
||||
|
||||
@property
|
||||
def results(self):
|
||||
data = POINTER(c_double)()
|
||||
shape = (c_int*3)()
|
||||
_dll.openmc_tally_results(self._index, data, shape)
|
||||
return as_array(data, tuple(shape[::-1]))
|
||||
|
||||
@filters.setter
|
||||
def filters(self, filters):
|
||||
# Get filter indices as int32_t[]
|
||||
|
|
@ -153,15 +202,60 @@ class Tally(_FortranObjectWithID):
|
|||
|
||||
_dll.openmc_tally_set_filters(self._index, n, indices)
|
||||
|
||||
@property
|
||||
def mean(self):
|
||||
n = self.num_realizations
|
||||
sum_ = self.results[:, :, 1]
|
||||
if n > 0:
|
||||
return sum_ / n
|
||||
else:
|
||||
return sum_.copy()
|
||||
|
||||
@property
|
||||
def nuclides(self):
|
||||
nucs = POINTER(c_int)()
|
||||
n = c_int()
|
||||
_dll.openmc_tally_get_nuclides(self._index, nucs, n)
|
||||
return [Nuclide(nucs[i]).name if nucs[i] > 0 else 'total'
|
||||
for i in range(n.value)]
|
||||
|
||||
@nuclides.setter
|
||||
def nuclides(self, nuclides):
|
||||
nucs = (c_char_p * len(nuclides))()
|
||||
nucs[:] = [x.encode() for x in nuclides]
|
||||
_dll.openmc_tally_set_nuclides(self._index, len(nuclides), nucs)
|
||||
|
||||
@property
|
||||
def num_realizations(self):
|
||||
n = c_int32()
|
||||
_dll.openmc_tally_get_n_realizations(self._index, n)
|
||||
return n.value
|
||||
|
||||
@property
|
||||
def results(self):
|
||||
data = POINTER(c_double)()
|
||||
shape = (c_int*3)()
|
||||
_dll.openmc_tally_results(self._index, data, shape)
|
||||
return as_array(data, tuple(shape[::-1]))
|
||||
|
||||
@property
|
||||
def scores(self):
|
||||
pass
|
||||
scores_as_int = POINTER(c_int)()
|
||||
n = c_int()
|
||||
try:
|
||||
_dll.openmc_tally_get_scores(self._index, scores_as_int, n)
|
||||
except AllocationError:
|
||||
return []
|
||||
else:
|
||||
scores = []
|
||||
for i in range(n.value):
|
||||
if scores_as_int[i] in _SCORES:
|
||||
scores.append(_SCORES[scores_as_int[i]])
|
||||
elif scores_as_int[i] in REACTION_NAME:
|
||||
scores.append(REACTION_NAME[scores_as_int[i]])
|
||||
else:
|
||||
scores.append(str(scores_as_int[i]))
|
||||
return scores
|
||||
|
||||
@scores.setter
|
||||
def scores(self, scores):
|
||||
|
|
@ -169,21 +263,47 @@ class Tally(_FortranObjectWithID):
|
|||
scores_[:] = [x.encode() for x in scores]
|
||||
_dll.openmc_tally_set_scores(self._index, len(scores), scores_)
|
||||
|
||||
@classmethod
|
||||
def new(cls, tally_id=None):
|
||||
# Determine ID to assign
|
||||
if tally_id is None:
|
||||
try:
|
||||
tally_id = max(tallies) + 1
|
||||
except ValueError:
|
||||
tally_id = 1
|
||||
@property
|
||||
def std_dev(self):
|
||||
results = self.results
|
||||
std_dev = np.empty(results.shape[:2])
|
||||
std_dev.fill(np.inf)
|
||||
|
||||
index = c_int32()
|
||||
_dll.openmc_extend_tallies(1, index, None)
|
||||
_dll.openmc_tally_set_type(index, b'generic')
|
||||
tally = cls(index.value)
|
||||
tally.id = tally_id
|
||||
return tally
|
||||
n = self.num_realizations
|
||||
if n > 1:
|
||||
# Get sum and sum-of-squares from results
|
||||
sum_ = results[:, :, 1]
|
||||
sum_sq = results[:, :, 2]
|
||||
|
||||
# Determine non-zero entries
|
||||
mean = sum_ / n
|
||||
nonzero = np.abs(mean) > 0
|
||||
|
||||
# Calculate sample standard deviation of the mean
|
||||
std_dev[nonzero] = np.sqrt(
|
||||
(sum_sq[nonzero]/n - mean[nonzero]**2)/(n - 1))
|
||||
|
||||
return std_dev
|
||||
|
||||
def ci_width(self, alpha=0.05):
|
||||
"""Confidence interval half-width based on a Student t distribution
|
||||
|
||||
Parameters
|
||||
----------
|
||||
alpha : float
|
||||
Significance level (one minus the confidence level!)
|
||||
|
||||
Returns
|
||||
-------
|
||||
float
|
||||
Half-width of a two-sided (1 - :math:`alpha`) confidence interval
|
||||
|
||||
"""
|
||||
half_width = self.std_dev.copy()
|
||||
n = self.num_realizations
|
||||
if n > 1:
|
||||
half_width *= scipy.stats.t.ppf(1 - alpha/2, n - 1)
|
||||
return half_width
|
||||
|
||||
|
||||
class _TallyMapping(Mapping):
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
from collections import OrderedDict, Iterable
|
||||
from collections import OrderedDict
|
||||
from collections.abc import Iterable
|
||||
from copy import deepcopy
|
||||
from math import cos, sin, pi
|
||||
from numbers import Real, Integral
|
||||
|
|
@ -6,7 +7,6 @@ from xml.etree import ElementTree as ET
|
|||
import sys
|
||||
import warnings
|
||||
|
||||
from six import string_types
|
||||
import numpy as np
|
||||
|
||||
import openmc
|
||||
|
|
@ -108,32 +108,6 @@ class Cell(IDManagerMixin):
|
|||
else:
|
||||
return point in self.region
|
||||
|
||||
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.temperature != other.temperature:
|
||||
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 += '{: <16}=\t{}\n'.format('\tID', self.id)
|
||||
|
|
@ -229,7 +203,7 @@ class Cell(IDManagerMixin):
|
|||
@name.setter
|
||||
def name(self, name):
|
||||
if name is not None:
|
||||
cv.check_type('cell name', name, string_types)
|
||||
cv.check_type('cell name', name, str)
|
||||
self._name = name
|
||||
else:
|
||||
self._name = ''
|
||||
|
|
@ -237,14 +211,7 @@ class Cell(IDManagerMixin):
|
|||
@fill.setter
|
||||
def fill(self, fill):
|
||||
if fill is not None:
|
||||
if isinstance(fill, string_types):
|
||||
if fill.strip().lower() != 'void':
|
||||
msg = 'Unable to set Cell ID="{0}" to use a non-Material ' \
|
||||
'or Universe fill "{1}"'.format(self._id, fill)
|
||||
raise ValueError(msg)
|
||||
fill = None
|
||||
|
||||
elif isinstance(fill, Iterable):
|
||||
if isinstance(fill, Iterable):
|
||||
for i, f in enumerate(fill):
|
||||
if f is not None:
|
||||
cv.check_type('cell.fill[i]', f, openmc.Material)
|
||||
|
|
@ -317,50 +284,6 @@ class Cell(IDManagerMixin):
|
|||
cv.check_type('cell volume', volume, Real)
|
||||
self._volume = volume
|
||||
|
||||
def add_surface(self, surface, halfspace):
|
||||
"""Add a half-space to the list of half-spaces whose intersection defines the
|
||||
cell.
|
||||
|
||||
.. deprecated:: 0.7.1
|
||||
Use the :attr:`Cell.region` property to directly specify a Region
|
||||
expression.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
surface : openmc.Surface
|
||||
Quadric surface dividing space
|
||||
halfspace : {-1, 1}
|
||||
Indicate whether the negative or positive half-space is to be used
|
||||
|
||||
"""
|
||||
|
||||
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)
|
||||
raise ValueError(msg)
|
||||
|
||||
if halfspace not in [-1, +1]:
|
||||
msg = 'Unable to add Surface "{0}" to Cell ID="{1}" with halfspace ' \
|
||||
'"{2}" since it is not +/-1'.format(surface, self._id, halfspace)
|
||||
raise ValueError(msg)
|
||||
|
||||
# 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 &= region
|
||||
else:
|
||||
self.region = Intersection(self.region, region)
|
||||
|
||||
def add_volume_information(self, volume_calc):
|
||||
"""Add volume information to a cell.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import copy
|
||||
from collections import Iterable
|
||||
from collections.abc import Iterable
|
||||
|
||||
import numpy as np
|
||||
|
||||
|
|
@ -246,9 +246,9 @@ def check_filetype_version(obj, expected_type, expected_version):
|
|||
----------
|
||||
obj : h5py.File
|
||||
HDF5 file to check
|
||||
expected_type
|
||||
expected_type : str
|
||||
Expected file type, e.g. 'statepoint'
|
||||
expected_version
|
||||
expected_version : int
|
||||
Expected major version number.
|
||||
|
||||
"""
|
||||
|
|
@ -288,7 +288,7 @@ class CheckedList(list):
|
|||
"""
|
||||
|
||||
def __init__(self, expected_type, name, items=[]):
|
||||
super(CheckedList, self).__init__()
|
||||
super().__init__()
|
||||
self.expected_type = expected_type
|
||||
self.name = name
|
||||
for item in items:
|
||||
|
|
@ -319,7 +319,7 @@ class CheckedList(list):
|
|||
|
||||
"""
|
||||
check_type(self.name, item, self.expected_type)
|
||||
super(CheckedList, self).append(item)
|
||||
super().append(item)
|
||||
|
||||
def insert(self, index, item):
|
||||
"""Insert item before index
|
||||
|
|
@ -333,4 +333,4 @@ class CheckedList(list):
|
|||
|
||||
"""
|
||||
check_type(self.name, item, self.expected_type)
|
||||
super(CheckedList, self).insert(index, item)
|
||||
super().insert(index, item)
|
||||
|
|
|
|||
|
|
@ -1,70 +1,3 @@
|
|||
def sort_xml_elements(tree):
|
||||
|
||||
# Retrieve all children of the root XML node in the tree
|
||||
elements = list(tree)
|
||||
|
||||
# Initialize empty lists for the sorted and comment elements
|
||||
sorted_elements = []
|
||||
|
||||
# Initialize an empty set of tags (e.g., Surface, Cell, and Lattice)
|
||||
tags = set()
|
||||
|
||||
# Find the unique tags in the tree
|
||||
for element in elements:
|
||||
tags.add(element.tag)
|
||||
|
||||
# Initialize an empty list for the comment elements
|
||||
comment_elements = []
|
||||
|
||||
# Find the comment elements and record their ordering within the
|
||||
# tree using a precedence with respect to the subsequent nodes
|
||||
for index, element in enumerate(elements):
|
||||
next_element = None
|
||||
|
||||
if 'Comment' in str(element.tag):
|
||||
|
||||
if index < len(elements)-1:
|
||||
next_element = elements[index+1]
|
||||
|
||||
comment_elements.append((element, next_element))
|
||||
|
||||
# Now iterate over all tags and order the elements within each tag
|
||||
for tag in sorted(list(tags)):
|
||||
|
||||
# Retrieve all of the elements for this tag
|
||||
try:
|
||||
tagged_elements = tree.findall(tag)
|
||||
except:
|
||||
continue
|
||||
|
||||
# Initialize an empty list of tuples to sort (id, element)
|
||||
tagged_data = []
|
||||
|
||||
# Retrieve the IDs for each of the elements
|
||||
for element in tagged_elements:
|
||||
key = element.get('id')
|
||||
|
||||
# If this element has an "ID" tag, append it to the list to sort
|
||||
if key is not None:
|
||||
tagged_data.append((int(key), element))
|
||||
|
||||
# Sort the elements according to the IDs for this tag
|
||||
tagged_data.sort()
|
||||
sorted_elements.extend(list(item[-1] for item in tagged_data))
|
||||
|
||||
# Add the comment elements while preserving the original precedence
|
||||
for element, next_element in comment_elements:
|
||||
index = sorted_elements.index(next_element)
|
||||
sorted_elements.insert(index, element)
|
||||
|
||||
# Remove all of the sorted elements from the tree
|
||||
for element in sorted_elements:
|
||||
tree.remove(element)
|
||||
|
||||
# Add the sorted elements back to the tree in the proper order
|
||||
tree.extend(sorted_elements)
|
||||
|
||||
|
||||
def clean_xml_indentation(element, level=0, spaces_per_level=2):
|
||||
"""
|
||||
copy and paste from http://effbot.org/zone/elementent-lib.htm#prettyprint
|
||||
|
|
|
|||
|
|
@ -10,13 +10,11 @@ References
|
|||
|
||||
"""
|
||||
|
||||
from collections import Iterable
|
||||
from collections.abc import Iterable
|
||||
from numbers import Real, Integral
|
||||
from xml.etree import ElementTree as ET
|
||||
import sys
|
||||
|
||||
from six import string_types
|
||||
|
||||
from openmc.clean_xml import clean_xml_indentation
|
||||
from openmc.checkvalue import (check_type, check_length, check_value,
|
||||
check_greater_than, check_less_than)
|
||||
|
|
@ -338,7 +336,7 @@ class CMFD(object):
|
|||
|
||||
@display.setter
|
||||
def display(self, display):
|
||||
check_type('CMFD display', display, string_types)
|
||||
check_type('CMFD display', display, str)
|
||||
check_value('CMFD display', display,
|
||||
['balance', 'dominance', 'entropy', 'source'])
|
||||
self._display = display
|
||||
|
|
|
|||
|
|
@ -15,12 +15,10 @@ generates ACE-format cross sections.
|
|||
|
||||
"""
|
||||
|
||||
from __future__ import division, unicode_literals
|
||||
from os import SEEK_CUR
|
||||
import struct
|
||||
import sys
|
||||
|
||||
from six import string_types
|
||||
import numpy as np
|
||||
|
||||
from openmc.mixin import EqualityMixin
|
||||
|
|
@ -153,7 +151,7 @@ class Library(EqualityMixin):
|
|||
"""
|
||||
|
||||
def __init__(self, filename, table_names=None, verbose=False):
|
||||
if isinstance(table_names, string_types):
|
||||
if isinstance(table_names, str):
|
||||
table_names = [table_names]
|
||||
if table_names is not None:
|
||||
table_names = set(table_names)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from collections import Iterable
|
||||
from collections.abc import Iterable
|
||||
from io import StringIO
|
||||
from numbers import Real
|
||||
from warnings import warn
|
||||
|
|
@ -34,7 +34,7 @@ class AngleDistribution(EqualityMixin):
|
|||
"""
|
||||
|
||||
def __init__(self, energy, mu):
|
||||
super(AngleDistribution, self).__init__()
|
||||
super().__init__()
|
||||
self.energy = energy
|
||||
self.mu = mu
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +1,11 @@
|
|||
from abc import ABCMeta, abstractmethod
|
||||
from io import StringIO
|
||||
|
||||
from six import add_metaclass
|
||||
|
||||
import openmc.data
|
||||
from openmc.mixin import EqualityMixin
|
||||
|
||||
|
||||
@add_metaclass(ABCMeta)
|
||||
class AngleEnergy(EqualityMixin):
|
||||
class AngleEnergy(EqualityMixin, metaclass=ABCMeta):
|
||||
"""Distribution in angle and energy of a secondary particle."""
|
||||
@abstractmethod
|
||||
def to_hdf5(self, group):
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from collections import Iterable
|
||||
from collections.abc import Iterable
|
||||
from numbers import Real, Integral
|
||||
from warnings import warn
|
||||
|
||||
|
|
@ -45,7 +45,7 @@ class CorrelatedAngleEnergy(AngleEnergy):
|
|||
"""
|
||||
|
||||
def __init__(self, breakpoints, interpolation, energy, energy_out, mu):
|
||||
super(CorrelatedAngleEnergy, self).__init__()
|
||||
super().__init__()
|
||||
self.breakpoints = breakpoints
|
||||
self.interpolation = interpolation
|
||||
self.energy = energy
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
import itertools
|
||||
import os
|
||||
import re
|
||||
from warnings import warn
|
||||
|
||||
from numpy import sqrt
|
||||
|
||||
|
||||
# Isotopic abundances from Meija J, Coplen T B, et al, "Isotopic compositions
|
||||
|
|
@ -208,14 +211,165 @@ def atomic_weight(element):
|
|||
return None if weight == 0. else weight
|
||||
|
||||
|
||||
def water_density(temperature, pressure=0.1013):
|
||||
"""Return the density of liquid water at a given temperature and pressure.
|
||||
|
||||
The density is calculated from a polynomial fit using equations and values
|
||||
from the 2012 version of the IAPWS-IF97 formulation. Only the equations
|
||||
for region 1 are implemented here. Region 1 is limited to liquid water
|
||||
below 100 [MPa] with a temperature above 273.15 [K], below 623.15 [K], and
|
||||
below saturation.
|
||||
|
||||
Reference: International Association for the Properties of Water and Steam,
|
||||
"Revised Release on the IAPWS Industrial Formulation 1997 for the
|
||||
Thermodynamic Properties of Water and Steam", IAPWS R7-97(2012).
|
||||
|
||||
Parameters
|
||||
----------
|
||||
temperature : float
|
||||
Water temperature in units of [K]
|
||||
pressure : float
|
||||
Water pressure in units of [MPa]
|
||||
|
||||
Returns
|
||||
-------
|
||||
float
|
||||
Water density in units of [g / cm^3]
|
||||
|
||||
"""
|
||||
|
||||
# Make sure the temperature and pressure are inside the min/max region 1
|
||||
# bounds. (Relax the 273.15 bound to 273 in case a user wants 0 deg C data
|
||||
# but they only use 3 digits for their conversion to K.)
|
||||
if pressure > 100.0:
|
||||
warn("Results are not valid for pressures above 100 MPa.")
|
||||
if pressure < 0.0:
|
||||
warn("Results are not valid for pressures below zero.")
|
||||
if temperature < 273:
|
||||
warn("Results are not valid for temperatures below 273.15 K.")
|
||||
if temperature > 623.15:
|
||||
warn("Results are not valid for temperatures above 623.15 K.")
|
||||
|
||||
# IAPWS region 4 parameters
|
||||
n4 = [0.11670521452767e4, -0.72421316703206e6, -0.17073846940092e2,
|
||||
0.12020824702470e5, -0.32325550322333e7, 0.14915108613530e2,
|
||||
-0.48232657361591e4, 0.40511340542057e6, -0.23855557567849,
|
||||
0.65017534844798e3]
|
||||
|
||||
# Compute the saturation temperature at the given pressure.
|
||||
beta = pressure**(0.25)
|
||||
E = beta**2 + n4[2] * beta + n4[5]
|
||||
F = n4[0] * beta**2 + n4[3] * beta + n4[6]
|
||||
G = n4[1] * beta**2 + n4[4] * beta + n4[7]
|
||||
D = 2.0 * G / (-F - sqrt(F**2 - 4 * E * G))
|
||||
T_sat = 0.5 * (n4[9] + D
|
||||
- sqrt((n4[9] + D)**2 - 4.0 * (n4[8] + n4[9] * D)))
|
||||
|
||||
# Make sure we aren't above saturation. (Relax this bound by .2 degrees
|
||||
# for deg C to K conversions.)
|
||||
if temperature > T_sat + 0.2:
|
||||
warn("Results are not valid for temperatures above saturation "
|
||||
"(above the boiling point).")
|
||||
|
||||
# IAPWS region 1 parameters
|
||||
R_GAS_CONSTANT = 0.461526 # kJ / kg / K
|
||||
ref_p = 16.53 # MPa
|
||||
ref_T = 1386 # K
|
||||
n1f = [0.14632971213167, -0.84548187169114, -0.37563603672040e1,
|
||||
0.33855169168385e1, -0.95791963387872, 0.15772038513228,
|
||||
-0.16616417199501e-1, 0.81214629983568e-3, 0.28319080123804e-3,
|
||||
-0.60706301565874e-3, -0.18990068218419e-1, -0.32529748770505e-1,
|
||||
-0.21841717175414e-1, -0.52838357969930e-4, -0.47184321073267e-3,
|
||||
-0.30001780793026e-3, 0.47661393906987e-4, -0.44141845330846e-5,
|
||||
-0.72694996297594e-15, -0.31679644845054e-4, -0.28270797985312e-5,
|
||||
-0.85205128120103e-9, -0.22425281908000e-5, -0.65171222895601e-6,
|
||||
-0.14341729937924e-12, -0.40516996860117e-6, -0.12734301741641e-8,
|
||||
-0.17424871230634e-9, -0.68762131295531e-18, 0.14478307828521e-19,
|
||||
0.26335781662795e-22, -0.11947622640071e-22, 0.18228094581404e-23,
|
||||
-0.93537087292458e-25]
|
||||
I1f = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4,
|
||||
4, 4, 5, 8, 8, 21, 23, 29, 30, 31, 32]
|
||||
J1f = [-2, -1, 0, 1, 2, 3, 4, 5, -9, -7, -1, 0, 1, 3, -3, 0, 1, 3, 17, -4,
|
||||
0, 6, -5, -2, 10, -8, -11, -6, -29, -31, -38, -39, -40, -41]
|
||||
|
||||
# Nondimensionalize the pressure and temperature.
|
||||
pi = pressure / ref_p
|
||||
tau = ref_T / temperature
|
||||
|
||||
# Compute the derivative of gamma (dimensionless Gibbs free energy) with
|
||||
# respect to pi.
|
||||
gamma1_pi = 0.0
|
||||
for n, I, J in zip(n1f, I1f, J1f):
|
||||
gamma1_pi -= n * I * (7.1 - pi)**(I - 1) * (tau - 1.222)**J
|
||||
|
||||
# Compute the leading coefficient. This sets the units at
|
||||
# 1 [MPa] * [kg K / kJ] * [1 / K]
|
||||
# = 1e6 [N / m^2] * 1e-3 [kg K / N / m] * [1 / K]
|
||||
# = 1e3 [kg / m^3]
|
||||
# = 1 [g / cm^3]
|
||||
coeff = pressure / R_GAS_CONSTANT / temperature
|
||||
|
||||
# Compute and return the density.
|
||||
return coeff / pi / gamma1_pi
|
||||
|
||||
|
||||
def gnd_name(Z, A, m=0):
|
||||
"""Return nuclide name using GND convention
|
||||
|
||||
Parameters
|
||||
----------
|
||||
Z : int
|
||||
Atomic number
|
||||
A : int
|
||||
Mass number
|
||||
m : int, optional
|
||||
Metastable state
|
||||
|
||||
Returns
|
||||
-------
|
||||
str
|
||||
Nuclide name in GND convention, e.g., 'Am242_m1'
|
||||
|
||||
"""
|
||||
if m > 0:
|
||||
return '{}{}_m{}'.format(ATOMIC_SYMBOL[Z], A, m)
|
||||
else:
|
||||
return '{}{}'.format(ATOMIC_SYMBOL[Z], A)
|
||||
|
||||
|
||||
def zam(name):
|
||||
"""Return tuple of (atomic number, mass number, metastable state)
|
||||
|
||||
Parameters
|
||||
----------
|
||||
name : str
|
||||
Name of nuclide using GND convention, e.g., 'Am242_m1'
|
||||
|
||||
Returns
|
||||
-------
|
||||
3-tuple of int
|
||||
Atomic number, mass number, and metastable state
|
||||
|
||||
"""
|
||||
try:
|
||||
symbol, A, state = re.match(r'([A-Zn][a-z]*)(\d+)((?:_[em]\d+)?)',
|
||||
name).groups()
|
||||
except AttributeError:
|
||||
raise ValueError("'{}' does not appear to be a nuclide name in GND "
|
||||
"format.".format(name))
|
||||
metastable = int(state[2:]) if state else 0
|
||||
return (ATOMIC_NUMBER[symbol], int(A), metastable)
|
||||
|
||||
|
||||
# Values here are from the Committee on Data for Science and Technology
|
||||
# (CODATA) 2014 recommendation (doi:10.1103/RevModPhys.88.035009).
|
||||
|
||||
# The value of the Boltzman constant in units of eV / K
|
||||
K_BOLTZMANN = 8.6173303e-5
|
||||
|
||||
# Used for converting units in ACE data
|
||||
# Unit conversions
|
||||
EV_PER_MEV = 1.0e6
|
||||
JOULE_PER_EV = 1.6021766208e-19
|
||||
|
||||
# Avogadro's constant
|
||||
AVOGADRO = 6.022140857e23
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
from collections import Iterable, namedtuple
|
||||
from collections import namedtuple
|
||||
from collections.abc import Iterable
|
||||
from io import StringIO
|
||||
from math import log
|
||||
from numbers import Real
|
||||
import re
|
||||
from warnings import warn
|
||||
|
||||
from six import string_types
|
||||
import numpy as np
|
||||
try:
|
||||
from uncertainties import ufloat, unumpy, UFloat
|
||||
|
|
@ -278,12 +278,12 @@ class DecayMode(EqualityMixin):
|
|||
|
||||
@modes.setter
|
||||
def modes(self, modes):
|
||||
cv.check_type('decay modes', modes, Iterable, string_types)
|
||||
cv.check_type('decay modes', modes, Iterable, str)
|
||||
self._modes = modes
|
||||
|
||||
@parent.setter
|
||||
def parent(self, parent):
|
||||
cv.check_type('parent nuclide', parent, string_types)
|
||||
cv.check_type('parent nuclide', parent, str)
|
||||
self._parent = parent
|
||||
|
||||
|
||||
|
|
@ -457,6 +457,7 @@ class Decay(EqualityMixin):
|
|||
items, values = get_list_record(file_obj)
|
||||
self.nuclide['spin'] = items[0]
|
||||
self.nuclide['parity'] = items[1]
|
||||
self.half_life = ufloat(float('inf'), float('inf'))
|
||||
|
||||
@property
|
||||
def decay_constant(self):
|
||||
|
|
|
|||
|
|
@ -6,19 +6,18 @@ Data File ENDF-6". The latest version from June 2009 can be found at
|
|||
http://www-nds.iaea.org/ndspub/documents/endf/endf102/endf102.pdf
|
||||
|
||||
"""
|
||||
from __future__ import print_function, division, unicode_literals
|
||||
|
||||
import io
|
||||
import re
|
||||
import os
|
||||
from math import pi
|
||||
from collections import OrderedDict, Iterable
|
||||
from pathlib import PurePath
|
||||
from collections import OrderedDict
|
||||
from collections.abc import Iterable
|
||||
|
||||
from six import string_types
|
||||
import numpy as np
|
||||
from numpy.polynomial.polynomial import Polynomial
|
||||
|
||||
from .data import ATOMIC_SYMBOL
|
||||
from .data import ATOMIC_SYMBOL, gnd_name
|
||||
from .function import Tabulated1D, INTERPOLATION_SCHEME
|
||||
from openmc.stats.univariate import Uniform, Tabular, Legendre
|
||||
|
||||
|
|
@ -270,6 +269,7 @@ def get_tab2_record(file_obj):
|
|||
|
||||
return params, Tabulated2D(breakpoints, interpolation)
|
||||
|
||||
|
||||
def get_evaluations(filename):
|
||||
"""Return a list of all evaluations within an ENDF file.
|
||||
|
||||
|
|
@ -321,8 +321,8 @@ class Evaluation(object):
|
|||
|
||||
"""
|
||||
def __init__(self, filename_or_obj):
|
||||
if isinstance(filename_or_obj, string_types):
|
||||
fh = open(filename_or_obj, 'r')
|
||||
if isinstance(filename_or_obj, (str, PurePath)):
|
||||
fh = open(str(filename_or_obj), 'r')
|
||||
else:
|
||||
fh = filename_or_obj
|
||||
self.section = {}
|
||||
|
|
@ -452,13 +452,9 @@ class Evaluation(object):
|
|||
|
||||
@property
|
||||
def gnd_name(self):
|
||||
symbol = ATOMIC_SYMBOL[self.target['atomic_number']]
|
||||
A = self.target['mass_number']
|
||||
m = self.target['isomeric_state']
|
||||
if m > 0:
|
||||
return '{}{}_m{}'.format(symbol, A, m)
|
||||
else:
|
||||
return '{}{}'.format(symbol, A)
|
||||
return gnd_name(self.target['atomic_number'],
|
||||
self.target['mass_number'],
|
||||
self.target['isomeric_state'])
|
||||
|
||||
|
||||
class Tabulated2D(object):
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
from abc import ABCMeta, abstractmethod
|
||||
from collections import Iterable
|
||||
from collections.abc import Iterable
|
||||
from numbers import Integral, Real
|
||||
from warnings import warn
|
||||
|
||||
from six import add_metaclass
|
||||
import numpy as np
|
||||
|
||||
from .function import Tabulated1D, INTERPOLATION_SCHEME
|
||||
|
|
@ -14,8 +13,7 @@ from .data import EV_PER_MEV
|
|||
from .endf import get_tab1_record, get_tab2_record
|
||||
|
||||
|
||||
@add_metaclass(ABCMeta)
|
||||
class EnergyDistribution(EqualityMixin):
|
||||
class EnergyDistribution(EqualityMixin, metaclass=ABCMeta):
|
||||
"""Abstract superclass for all energy distributions."""
|
||||
def __init__(self):
|
||||
pass
|
||||
|
|
@ -116,7 +114,7 @@ class ArbitraryTabulated(EnergyDistribution):
|
|||
"""
|
||||
|
||||
def __init__(self, energy, pdf):
|
||||
super(ArbitraryTabulated, self).__init__()
|
||||
super().__init__()
|
||||
self.energy = energy
|
||||
self.pdf = pdf
|
||||
|
||||
|
|
@ -184,7 +182,7 @@ class GeneralEvaporation(EnergyDistribution):
|
|||
"""
|
||||
|
||||
def __init__(self, theta, g, u):
|
||||
super(GeneralEvaporation, self).__init__()
|
||||
super().__init__()
|
||||
self.theta = theta
|
||||
self.g = g
|
||||
self.u = u
|
||||
|
|
@ -247,7 +245,7 @@ class MaxwellEnergy(EnergyDistribution):
|
|||
"""
|
||||
|
||||
def __init__(self, theta, u):
|
||||
super(MaxwellEnergy, self).__init__()
|
||||
super().__init__()
|
||||
self.theta = theta
|
||||
self.u = u
|
||||
|
||||
|
|
@ -380,7 +378,7 @@ class Evaporation(EnergyDistribution):
|
|||
"""
|
||||
|
||||
def __init__(self, theta, u):
|
||||
super(Evaporation, self).__init__()
|
||||
super().__init__()
|
||||
self.theta = theta
|
||||
self.u = u
|
||||
|
||||
|
|
@ -516,7 +514,7 @@ class WattEnergy(EnergyDistribution):
|
|||
"""
|
||||
|
||||
def __init__(self, a, b, u):
|
||||
super(WattEnergy, self).__init__()
|
||||
super().__init__()
|
||||
self.a = a
|
||||
self.b = b
|
||||
self.u = u
|
||||
|
|
@ -684,7 +682,7 @@ class MadlandNix(EnergyDistribution):
|
|||
"""
|
||||
|
||||
def __init__(self, efl, efh, tm):
|
||||
super(MadlandNix, self).__init__()
|
||||
super().__init__()
|
||||
self.efl = efl
|
||||
self.efh = efh
|
||||
self.tm = tm
|
||||
|
|
@ -807,7 +805,7 @@ class DiscretePhoton(EnergyDistribution):
|
|||
"""
|
||||
|
||||
def __init__(self, primary_flag, energy, atomic_weight_ratio):
|
||||
super(DiscretePhoton, self).__init__()
|
||||
super().__init__()
|
||||
self.primary_flag = primary_flag
|
||||
self.energy = energy
|
||||
self.atomic_weight_ratio = atomic_weight_ratio
|
||||
|
|
@ -916,7 +914,7 @@ class LevelInelastic(EnergyDistribution):
|
|||
"""
|
||||
|
||||
def __init__(self, threshold, mass_ratio):
|
||||
super(LevelInelastic, self).__init__()
|
||||
super().__init__()
|
||||
self.threshold = threshold
|
||||
self.mass_ratio = mass_ratio
|
||||
|
||||
|
|
@ -1021,7 +1019,7 @@ class ContinuousTabular(EnergyDistribution):
|
|||
"""
|
||||
|
||||
def __init__(self, breakpoints, interpolation, energy, energy_out):
|
||||
super(ContinuousTabular, self).__init__()
|
||||
super().__init__()
|
||||
self.breakpoints = breakpoints
|
||||
self.interpolation = interpolation
|
||||
self.energy = energy
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from collections import Callable
|
||||
from collections.abc import Callable
|
||||
from copy import deepcopy
|
||||
from io import StringIO
|
||||
import sys
|
||||
|
|
@ -107,7 +107,7 @@ def write_compact_458_library(endf_files, output_name='fission_Q_data.h5',
|
|||
|
||||
"""
|
||||
# Open the output file.
|
||||
out = h5py.File(output_name, 'w', libver='latest')
|
||||
out = h5py.File(output_name, 'w', libver='earliest')
|
||||
|
||||
# Write comments, if given. This commented out comment is the one used for
|
||||
# the library distributed with OpenMC.
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
from abc import ABCMeta, abstractmethod
|
||||
from collections import Iterable, Callable
|
||||
from collections.abc import Iterable, Callable
|
||||
from numbers import Real, Integral
|
||||
|
||||
from six import add_metaclass
|
||||
import numpy as np
|
||||
|
||||
import openmc.data
|
||||
|
|
@ -14,8 +13,7 @@ INTERPOLATION_SCHEME = {1: 'histogram', 2: 'linear-linear', 3: 'linear-log',
|
|||
4: 'log-linear', 5: 'log-log'}
|
||||
|
||||
|
||||
@add_metaclass(ABCMeta)
|
||||
class Function1D(EqualityMixin):
|
||||
class Function1D(EqualityMixin, metaclass=ABCMeta):
|
||||
"""A function of one independent variable with HDF5 support."""
|
||||
@abstractmethod
|
||||
def __call__(self): pass
|
||||
|
|
|
|||
|
|
@ -21,6 +21,9 @@ def linearize(x, f, tolerance=0.001):
|
|||
Tabulated values of the dependent variable
|
||||
|
||||
"""
|
||||
# Make sure x is a numpy array
|
||||
x = np.asarray(x)
|
||||
|
||||
# Initialize output arrays
|
||||
x_out = []
|
||||
y_out = []
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from collections import Iterable
|
||||
from collections.abc import Iterable
|
||||
from numbers import Real, Integral
|
||||
from warnings import warn
|
||||
|
||||
|
|
@ -53,7 +53,7 @@ class KalbachMann(AngleEnergy):
|
|||
|
||||
def __init__(self, breakpoints, interpolation, energy, energy_out,
|
||||
precompound, slope):
|
||||
super(KalbachMann, self).__init__()
|
||||
super().__init__()
|
||||
self.breakpoints = breakpoints
|
||||
self.interpolation = interpolation
|
||||
self.energy = energy
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from collections import Iterable
|
||||
from collections.abc import Iterable
|
||||
from numbers import Real, Integral
|
||||
|
||||
import numpy as np
|
||||
|
|
@ -44,7 +44,7 @@ class LaboratoryAngleEnergy(AngleEnergy):
|
|||
"""
|
||||
|
||||
def __init__(self, breakpoints, interpolation, energy, mu, energy_out):
|
||||
super(LaboratoryAngleEnergy).__init__()
|
||||
super().__init__()
|
||||
self.breakpoints = breakpoints
|
||||
self.interpolation = interpolation
|
||||
self.energy = energy
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import os
|
||||
import xml.etree.ElementTree as ET
|
||||
from six import string_types
|
||||
|
||||
import h5py
|
||||
|
||||
|
|
@ -131,7 +130,7 @@ class DataLibrary(EqualityMixin):
|
|||
raise ValueError("Either path or OPENMC_CROSS_SECTIONS "
|
||||
"environmental variable must be set")
|
||||
|
||||
check_type('path', path, string_types)
|
||||
check_type('path', path, str)
|
||||
|
||||
tree = ET.parse(path)
|
||||
root = tree.getroot()
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ from math import exp, erf, pi, sqrt
|
|||
|
||||
import h5py
|
||||
import numpy as np
|
||||
from six import string_types
|
||||
|
||||
from . import WMP_VERSION
|
||||
from .data import K_BOLTZMANN
|
||||
|
|
@ -300,7 +299,7 @@ class WindowedMultipole(EqualityMixin):
|
|||
@formalism.setter
|
||||
def formalism(self, formalism):
|
||||
if formalism is not None:
|
||||
cv.check_type('formalism', formalism, string_types)
|
||||
cv.check_type('formalism', formalism, str)
|
||||
cv.check_value('formalism', formalism, ('MLBW', 'RM'))
|
||||
self._formalism = formalism
|
||||
|
||||
|
|
@ -404,7 +403,7 @@ class WindowedMultipole(EqualityMixin):
|
|||
cv.check_type('curvefit', curvefit, np.ndarray)
|
||||
if len(curvefit.shape) != 3:
|
||||
raise ValueError('Multipole curvefit arrays must be 3D')
|
||||
if curvefit.shape[2] not in (2, 3): # sigT, sigA (and maybe sigF)
|
||||
if curvefit.shape[2] not in (2, 3): # sig_t, sig_a (maybe sig_f)
|
||||
raise ValueError('The third dimension of multipole curvefit'
|
||||
' arrays must have a length of 2 or 3')
|
||||
if not np.issubdtype(curvefit.dtype, float):
|
||||
|
|
@ -531,7 +530,6 @@ class WindowedMultipole(EqualityMixin):
|
|||
sqrtkT = sqrt(K_BOLTZMANN * T)
|
||||
sqrtE = sqrt(E)
|
||||
invE = 1.0 / E
|
||||
dopp = self.sqrtAWR / sqrtkT
|
||||
|
||||
# Locate us. The i_window calc omits a + 1 present in F90 because of
|
||||
# the 1-based vs. 0-based indexing. Similarly startw needs to be
|
||||
|
|
@ -546,7 +544,7 @@ class WindowedMultipole(EqualityMixin):
|
|||
# not appear in the absorption and fission equations.
|
||||
if startw <= endw:
|
||||
twophi = np.zeros(self.num_l, dtype=np.float)
|
||||
sigT_factor = np.zeros(self.num_l, dtype=np.cfloat)
|
||||
sig_t_factor = np.zeros(self.num_l, dtype=np.cfloat)
|
||||
|
||||
for iL in range(self.num_l):
|
||||
twophi[iL] = self.pseudo_k0RS[iL] * sqrtE
|
||||
|
|
@ -561,35 +559,36 @@ class WindowedMultipole(EqualityMixin):
|
|||
twophi[iL] = twophi[iL] - np.arctan(arg)
|
||||
|
||||
twophi = 2.0 * twophi
|
||||
sigT_factor = np.cos(twophi) - 1j*np.sin(twophi)
|
||||
sig_t_factor = np.cos(twophi) - 1j*np.sin(twophi)
|
||||
|
||||
# Initialize the ouptut cross sections.
|
||||
sigT = 0.0
|
||||
sigA = 0.0
|
||||
sigF = 0.0
|
||||
sig_t = 0.0
|
||||
sig_a = 0.0
|
||||
sig_f = 0.0
|
||||
|
||||
# ======================================================================
|
||||
# Add the contribution from the curvefit polynomial.
|
||||
|
||||
if sqrtkT != 0 and self.broaden_poly[i_window]:
|
||||
# Broaden the curvefit.
|
||||
dopp = self.sqrtAWR / sqrtkT
|
||||
broadened_polynomials = _broaden_wmp_polynomials(E, dopp,
|
||||
self.fit_order + 1)
|
||||
for i_poly in range(self.fit_order+1):
|
||||
sigT += (self.curvefit[i_window, i_poly, _FIT_T]
|
||||
* broadened_polynomials[i_poly])
|
||||
sigA += (self.curvefit[i_window, i_poly, _FIT_A]
|
||||
* broadened_polynomials[i_poly])
|
||||
sig_t += (self.curvefit[i_window, i_poly, _FIT_T]
|
||||
* broadened_polynomials[i_poly])
|
||||
sig_a += (self.curvefit[i_window, i_poly, _FIT_A]
|
||||
* broadened_polynomials[i_poly])
|
||||
if self.fissionable:
|
||||
sigF += (self.curvefit[i_window, i_poly, _FIT_F]
|
||||
* broadened_polynomials[i_poly])
|
||||
sig_f += (self.curvefit[i_window, i_poly, _FIT_F]
|
||||
* broadened_polynomials[i_poly])
|
||||
else:
|
||||
temp = invE
|
||||
for i_poly in range(self.fit_order+1):
|
||||
sigT += self.curvefit[i_window, i_poly, _FIT_T] * temp
|
||||
sigA += self.curvefit[i_window, i_poly, _FIT_A] * temp
|
||||
sig_t += self.curvefit[i_window, i_poly, _FIT_T] * temp
|
||||
sig_a += self.curvefit[i_window, i_poly, _FIT_A] * temp
|
||||
if self.fissionable:
|
||||
sigF += self.curvefit[i_window, i_poly, _FIT_F] * temp
|
||||
sig_f += self.curvefit[i_window, i_poly, _FIT_F] * temp
|
||||
temp *= sqrtE
|
||||
|
||||
# ======================================================================
|
||||
|
|
@ -601,45 +600,46 @@ class WindowedMultipole(EqualityMixin):
|
|||
psi_chi = -1j / (self.data[i_pole, _MP_EA] - sqrtE)
|
||||
c_temp = psi_chi / E
|
||||
if self.formalism == 'MLBW':
|
||||
sigT += ((self.data[i_pole, _MLBW_RT] * c_temp *
|
||||
sigT_factor[self.l_value[i_pole]-1]).real
|
||||
+ (self.data[i_pole, _MLBW_RX] * c_temp).real)
|
||||
sigA += (self.data[i_pole, _MLBW_RA] * c_temp).real
|
||||
sig_t += ((self.data[i_pole, _MLBW_RT] * c_temp *
|
||||
sig_t_factor[self.l_value[i_pole]-1]).real
|
||||
+ (self.data[i_pole, _MLBW_RX] * c_temp).real)
|
||||
sig_a += (self.data[i_pole, _MLBW_RA] * c_temp).real
|
||||
if self.fissionable:
|
||||
sigF += (self.data[i_pole, _MLBW_RF] * c_temp).real
|
||||
sig_f += (self.data[i_pole, _MLBW_RF] * c_temp).real
|
||||
elif self.formalism == 'RM':
|
||||
sigT += (self.data[i_pole, _RM_RT] * c_temp *
|
||||
sigT_factor[self.l_value[i_pole]-1]).real
|
||||
sigA += (self.data[i_pole, _RM_RA] * c_temp).real
|
||||
sig_t += (self.data[i_pole, _RM_RT] * c_temp *
|
||||
sig_t_factor[self.l_value[i_pole]-1]).real
|
||||
sig_a += (self.data[i_pole, _RM_RA] * c_temp).real
|
||||
if self.fissionable:
|
||||
sigF += (self.data[i_pole, _RM_RF] * c_temp).real
|
||||
sig_f += (self.data[i_pole, _RM_RF] * c_temp).real
|
||||
else:
|
||||
raise ValueError('Unrecognized/Unsupported R-matrix'
|
||||
' formalism')
|
||||
|
||||
else:
|
||||
# At temperature, use Faddeeva function-based form.
|
||||
dopp = self.sqrtAWR / sqrtkT
|
||||
for i_pole in range(startw, endw):
|
||||
Z = (sqrtE - self.data[i_pole, _MP_EA]) * dopp
|
||||
w_val = _faddeeva(Z) * dopp * invE * sqrt(pi)
|
||||
if self.formalism == 'MLBW':
|
||||
sigT += ((self.data[i_pole, _MLBW_RT] *
|
||||
sigT_factor[self.l_value[i_pole]-1] +
|
||||
self.data[i_pole, _MLBW_RX]) * w_val).real
|
||||
sigA += (self.data[i_pole, _MLBW_RA] * w_val).real
|
||||
sig_t += ((self.data[i_pole, _MLBW_RT] *
|
||||
sig_t_factor[self.l_value[i_pole]-1] +
|
||||
self.data[i_pole, _MLBW_RX]) * w_val).real
|
||||
sig_a += (self.data[i_pole, _MLBW_RA] * w_val).real
|
||||
if self.fissionable:
|
||||
sigF += (self.data[i_pole, _MLBW_RF] * w_val).real
|
||||
sig_f += (self.data[i_pole, _MLBW_RF] * w_val).real
|
||||
elif self.formalism == 'RM':
|
||||
sigT += (self.data[i_pole, _RM_RT] * w_val *
|
||||
sigT_factor[self.l_value[i_pole]-1]).real
|
||||
sigA += (self.data[i_pole, _RM_RA] * w_val).real
|
||||
sig_t += (self.data[i_pole, _RM_RT] * w_val *
|
||||
sig_t_factor[self.l_value[i_pole]-1]).real
|
||||
sig_a += (self.data[i_pole, _RM_RA] * w_val).real
|
||||
if self.fissionable:
|
||||
sigF += (self.data[i_pole, _RM_RF] * w_val).real
|
||||
sig_f += (self.data[i_pole, _RM_RF] * w_val).real
|
||||
else:
|
||||
raise ValueError('Unrecognized/Unsupported R-matrix'
|
||||
' formalism')
|
||||
|
||||
return sigT, sigA, sigF
|
||||
return sig_t, sig_a, sig_f
|
||||
|
||||
def __call__(self, E, T):
|
||||
"""Compute total, absorption, and fission cross sections.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
from __future__ import division, unicode_literals
|
||||
import sys
|
||||
from collections import OrderedDict, Iterable, Mapping, MutableMapping
|
||||
from collections import OrderedDict
|
||||
from collections.abc import Iterable, Mapping, MutableMapping
|
||||
from io import StringIO
|
||||
from itertools import chain
|
||||
from math import log10
|
||||
|
|
@ -10,7 +10,6 @@ import shutil
|
|||
import tempfile
|
||||
from warnings import warn
|
||||
|
||||
from six import string_types
|
||||
import numpy as np
|
||||
import h5py
|
||||
|
||||
|
|
@ -245,7 +244,7 @@ class IncidentNeutron(EqualityMixin):
|
|||
|
||||
@name.setter
|
||||
def name(self, name):
|
||||
cv.check_type('name', name, string_types)
|
||||
cv.check_type('name', name, str)
|
||||
self._name = name
|
||||
|
||||
@property
|
||||
|
|
@ -301,7 +300,7 @@ class IncidentNeutron(EqualityMixin):
|
|||
def urr(self, urr):
|
||||
cv.check_type('probability table dictionary', urr, MutableMapping)
|
||||
for key, value in urr:
|
||||
cv.check_type('probability table temperature', key, string_types)
|
||||
cv.check_type('probability table temperature', key, str)
|
||||
cv.check_type('probability tables', value, ProbabilityTables)
|
||||
self._urr = urr
|
||||
|
||||
|
|
@ -465,6 +464,8 @@ class IncidentNeutron(EqualityMixin):
|
|||
return [mt]
|
||||
elif mt in SUM_RULES:
|
||||
mts = SUM_RULES[mt]
|
||||
else:
|
||||
return []
|
||||
complete = False
|
||||
while not complete:
|
||||
new_mts = []
|
||||
|
|
@ -478,7 +479,7 @@ class IncidentNeutron(EqualityMixin):
|
|||
mts = new_mts
|
||||
return mts
|
||||
|
||||
def export_to_hdf5(self, path, mode='a'):
|
||||
def export_to_hdf5(self, path, mode='a', libver='earliest'):
|
||||
"""Export incident neutron data to an HDF5 file.
|
||||
|
||||
Parameters
|
||||
|
|
@ -488,6 +489,9 @@ class IncidentNeutron(EqualityMixin):
|
|||
mode : {'r', r+', 'w', 'x', 'a'}
|
||||
Mode that is used to open the HDF5 file. This is the second argument
|
||||
to the :class:`h5py.File` constructor.
|
||||
libver : {'earliest', 'latest'}
|
||||
Compatibility mode for the HDF5 file. 'latest' will produce files
|
||||
that are less backwards compatible but have performance benefits.
|
||||
|
||||
"""
|
||||
# If data come from ENDF, don't allow exporting to HDF5
|
||||
|
|
@ -496,7 +500,7 @@ class IncidentNeutron(EqualityMixin):
|
|||
'originated from an ENDF file.')
|
||||
|
||||
# Open file and write version
|
||||
f = h5py.File(path, mode, libver='latest')
|
||||
f = h5py.File(path, mode, libver=libver)
|
||||
f.attrs['filetype'] = np.string_('data_neutron')
|
||||
f.attrs['version'] = np.array(HDF5_VERSION)
|
||||
|
||||
|
|
@ -525,12 +529,6 @@ class IncidentNeutron(EqualityMixin):
|
|||
rx_group = rxs_group.create_group('reaction_{:03}'.format(rx.mt))
|
||||
rx.to_hdf5(rx_group)
|
||||
|
||||
# Write 0K elastic scattering if needed
|
||||
if '0K' in rx.xs and '0K' not in rx_group:
|
||||
group = rx_group.create_group('0K')
|
||||
dset = group.create_dataset('xs', data=rx.xs['0K'].y)
|
||||
dset.attrs['threshold_idx'] = 1
|
||||
|
||||
# Write total nu data if available
|
||||
if len(rx.derived_products) > 0 and 'total_nu' not in g:
|
||||
tgroup = g.create_group('total_nu')
|
||||
|
|
@ -844,10 +842,7 @@ class IncidentNeutron(EqualityMixin):
|
|||
Incident neutron continuous-energy data
|
||||
|
||||
"""
|
||||
# Create temporary directory -- it would be preferable to use
|
||||
# TemporaryDirectory(), but it is only available in Python 3.2
|
||||
tmpdir = tempfile.mkdtemp()
|
||||
try:
|
||||
with tempfile.TemporaryDirectory() as tmpdir:
|
||||
# Run NJOY to create an ACE library
|
||||
ace_file = os.path.join(tmpdir, 'ace')
|
||||
xsdir_file = os.path.join(tmpdir, 'xsdir')
|
||||
|
|
@ -875,8 +870,4 @@ class IncidentNeutron(EqualityMixin):
|
|||
data.energy['0K'] = xs.x
|
||||
data[2].xs['0K'] = xs
|
||||
|
||||
finally:
|
||||
# Get rid of temporary files
|
||||
shutil.rmtree(tmpdir)
|
||||
|
||||
return data
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
from __future__ import print_function
|
||||
import argparse
|
||||
from collections import namedtuple
|
||||
from io import StringIO
|
||||
import os
|
||||
import shutil
|
||||
from subprocess import Popen, PIPE, STDOUT
|
||||
from subprocess import Popen, PIPE, STDOUT, CalledProcessError
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
|
|
@ -139,10 +138,10 @@ def run(commands, tapein, tapeout, input_filename=None, stdout=False,
|
|||
njoy_exec : str, optional
|
||||
Path to NJOY executable
|
||||
|
||||
Returns
|
||||
-------
|
||||
int
|
||||
Return code of NJOY process
|
||||
Raises
|
||||
------
|
||||
subprocess.CalledProcessError
|
||||
If the NJOY process returns with a non-zero status
|
||||
|
||||
"""
|
||||
|
||||
|
|
@ -150,10 +149,7 @@ def run(commands, tapein, tapeout, input_filename=None, stdout=False,
|
|||
with open(input_filename, 'w') as f:
|
||||
f.write(commands)
|
||||
|
||||
# Create temporary directory -- it would be preferable to use
|
||||
# TemporaryDirectory(), but it is only available in Python 3.2
|
||||
tmpdir = tempfile.mkdtemp()
|
||||
try:
|
||||
with tempfile.TemporaryDirectory() as tmpdir:
|
||||
# Copy evaluations to appropriates 'tapes'
|
||||
for tape_num, filename in tapein.items():
|
||||
tmpfilename = os.path.join(tmpdir, 'tape{}'.format(tape_num))
|
||||
|
|
@ -165,25 +161,28 @@ def run(commands, tapein, tapeout, input_filename=None, stdout=False,
|
|||
|
||||
njoy.stdin.write(commands)
|
||||
njoy.stdin.flush()
|
||||
lines = []
|
||||
while True:
|
||||
# If process is finished, break loop
|
||||
line = njoy.stdout.readline()
|
||||
if not line and njoy.poll() is not None:
|
||||
break
|
||||
|
||||
lines.append(line)
|
||||
if stdout:
|
||||
# If user requested output, print to screen
|
||||
print(line, end='')
|
||||
|
||||
# Check for error
|
||||
if njoy.returncode != 0:
|
||||
raise CalledProcessError(njoy.returncode, njoy_exec,
|
||||
''.join(lines))
|
||||
|
||||
# Copy output files back to original directory
|
||||
for tape_num, filename in tapeout.items():
|
||||
tmpfilename = os.path.join(tmpdir, 'tape{}'.format(tape_num))
|
||||
if os.path.isfile(tmpfilename):
|
||||
shutil.move(tmpfilename, filename)
|
||||
finally:
|
||||
shutil.rmtree(tmpdir)
|
||||
|
||||
return njoy.returncode
|
||||
|
||||
|
||||
def make_pendf(filename, pendf='pendf', error=0.001, stdout=False):
|
||||
|
|
@ -200,15 +199,15 @@ def make_pendf(filename, pendf='pendf', error=0.001, stdout=False):
|
|||
stdout : bool
|
||||
Whether to display NJOY standard output
|
||||
|
||||
Returns
|
||||
-------
|
||||
int
|
||||
Return code of NJOY process
|
||||
Raises
|
||||
------
|
||||
subprocess.CalledProcessError
|
||||
If the NJOY process returns with a non-zero status
|
||||
|
||||
"""
|
||||
|
||||
return make_ace(filename, pendf=pendf, error=error, broadr=False,
|
||||
heatr=False, purr=False, acer=False, stdout=stdout)
|
||||
make_ace(filename, pendf=pendf, error=error, broadr=False,
|
||||
heatr=False, purr=False, acer=False, stdout=stdout)
|
||||
|
||||
|
||||
def make_ace(filename, temperatures=None, ace='ace', xsdir='xsdir', pendf=None,
|
||||
|
|
@ -238,14 +237,14 @@ def make_ace(filename, temperatures=None, ace='ace', xsdir='xsdir', pendf=None,
|
|||
purr : bool, optional
|
||||
Indicating whether to add probability table when running NJOY
|
||||
acer : bool, optional
|
||||
Indicating whether to generate ACE file when running NJOY
|
||||
Indicating whether to generate ACE file when running NJOY
|
||||
**kwargs
|
||||
Keyword arguments passed to :func:`openmc.data.njoy.run`
|
||||
|
||||
Returns
|
||||
-------
|
||||
int
|
||||
Return code of NJOY process
|
||||
Raises
|
||||
------
|
||||
subprocess.CalledProcessError
|
||||
If the NJOY process returns with a non-zero status
|
||||
|
||||
"""
|
||||
ev = endf.Evaluation(filename)
|
||||
|
|
@ -285,7 +284,7 @@ def make_ace(filename, temperatures=None, ace='ace', xsdir='xsdir', pendf=None,
|
|||
nheatr = nheatr_in + 1
|
||||
commands += _TEMPLATE_HEATR
|
||||
nlast = nheatr
|
||||
|
||||
|
||||
# purr
|
||||
if purr:
|
||||
npurr_in = nlast
|
||||
|
|
@ -310,9 +309,9 @@ def make_ace(filename, temperatures=None, ace='ace', xsdir='xsdir', pendf=None,
|
|||
tapeout[nace] = fname.format(ace, temperature)
|
||||
tapeout[ndir] = fname.format(xsdir, temperature)
|
||||
commands += 'stop\n'
|
||||
retcode = run(commands, tapein, tapeout, **kwargs)
|
||||
run(commands, tapein, tapeout, **kwargs)
|
||||
|
||||
if acer and retcode == 0:
|
||||
if acer:
|
||||
with open(ace, 'w') as ace_file, open(xsdir, 'w') as xsdir_file:
|
||||
for temperature in temperatures:
|
||||
# Get contents of ACE file
|
||||
|
|
@ -337,10 +336,8 @@ def make_ace(filename, temperatures=None, ace='ace', xsdir='xsdir', pendf=None,
|
|||
os.remove(fname.format(ace, temperature))
|
||||
os.remove(fname.format(xsdir, temperature))
|
||||
|
||||
return retcode
|
||||
|
||||
|
||||
def make_ace_thermal(filename, filename_thermal, temperatures=None,
|
||||
def make_ace_thermal(filename, filename_thermal, temperatures=None,
|
||||
ace='ace', xsdir='xsdir', error=0.001, **kwargs):
|
||||
"""Generate thermal scattering ACE file from ENDF files
|
||||
|
||||
|
|
@ -362,10 +359,10 @@ def make_ace_thermal(filename, filename_thermal, temperatures=None,
|
|||
**kwargs
|
||||
Keyword arguments passed to :func:`openmc.data.njoy.run`
|
||||
|
||||
Returns
|
||||
-------
|
||||
int
|
||||
Return code of NJOY process
|
||||
Raises
|
||||
------
|
||||
subprocess.CalledProcessError
|
||||
If the NJOY process returns with a non-zero status
|
||||
|
||||
"""
|
||||
ev = endf.Evaluation(filename)
|
||||
|
|
@ -461,21 +458,18 @@ def make_ace_thermal(filename, filename_thermal, temperatures=None,
|
|||
tapeout[nace] = fname.format(ace, temperature)
|
||||
tapeout[ndir] = fname.format(xsdir, temperature)
|
||||
commands += 'stop\n'
|
||||
retcode = run(commands, tapein, tapeout, **kwargs)
|
||||
run(commands, tapein, tapeout, **kwargs)
|
||||
|
||||
if retcode == 0:
|
||||
with open(ace, 'w') as ace_file, open(xsdir, 'w') as xsdir_file:
|
||||
# Concatenate ACE and xsdir files together
|
||||
for temperature in temperatures:
|
||||
text = open(fname.format(ace, temperature), 'r').read()
|
||||
ace_file.write(text)
|
||||
|
||||
text = open(fname.format(xsdir, temperature), 'r').read()
|
||||
xsdir_file.write(text)
|
||||
|
||||
# Remove ACE/xsdir files for each temperature
|
||||
with open(ace, 'w') as ace_file, open(xsdir, 'w') as xsdir_file:
|
||||
# Concatenate ACE and xsdir files together
|
||||
for temperature in temperatures:
|
||||
os.remove(fname.format(ace, temperature))
|
||||
os.remove(fname.format(xsdir, temperature))
|
||||
text = open(fname.format(ace, temperature), 'r').read()
|
||||
ace_file.write(text)
|
||||
|
||||
return retcode
|
||||
text = open(fname.format(xsdir, temperature), 'r').read()
|
||||
xsdir_file.write(text)
|
||||
|
||||
# Remove ACE/xsdir files for each temperature
|
||||
for temperature in temperatures:
|
||||
os.remove(fname.format(ace, temperature))
|
||||
os.remove(fname.format(xsdir, temperature))
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
from collections import Iterable
|
||||
from collections.abc import Iterable
|
||||
from io import StringIO
|
||||
from numbers import Real
|
||||
import sys
|
||||
|
||||
from six import string_types
|
||||
import numpy as np
|
||||
|
||||
import openmc.checkvalue as cv
|
||||
|
|
@ -113,7 +112,7 @@ class Product(EqualityMixin):
|
|||
|
||||
@particle.setter
|
||||
def particle(self, particle):
|
||||
cv.check_type('product particle type', particle, string_types)
|
||||
cv.check_type('product particle type', particle, str)
|
||||
self._particle = particle
|
||||
|
||||
@yield_.setter
|
||||
|
|
|
|||
|
|
@ -1,11 +1,9 @@
|
|||
from __future__ import division, unicode_literals
|
||||
from collections import Iterable, Callable, MutableMapping
|
||||
from collections.abc import Iterable, Callable, MutableMapping
|
||||
from copy import deepcopy
|
||||
from numbers import Real, Integral
|
||||
from warnings import warn
|
||||
from io import StringIO
|
||||
|
||||
from six import string_types
|
||||
import numpy as np
|
||||
|
||||
import openmc.checkvalue as cv
|
||||
|
|
@ -863,7 +861,7 @@ class Reaction(EqualityMixin):
|
|||
def xs(self, xs):
|
||||
cv.check_type('reaction cross section dictionary', xs, MutableMapping)
|
||||
for key, value in xs.items():
|
||||
cv.check_type('reaction cross section temperature', key, string_types)
|
||||
cv.check_type('reaction cross section temperature', key, str)
|
||||
cv.check_type('reaction cross section', value, Callable)
|
||||
self._xs = xs
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
from collections import defaultdict, MutableSequence, Iterable
|
||||
from collections import defaultdict
|
||||
from collections.abc import MutableSequence, Iterable
|
||||
import io
|
||||
|
||||
import numpy as np
|
||||
|
|
@ -288,8 +289,8 @@ class MultiLevelBreitWigner(ResonanceRange):
|
|||
"""
|
||||
|
||||
def __init__(self, target_spin, energy_min, energy_max, channel, scattering):
|
||||
super(MultiLevelBreitWigner, self).__init__(
|
||||
target_spin, energy_min, energy_max, channel, scattering)
|
||||
super().__init__(target_spin, energy_min, energy_max, channel,
|
||||
scattering)
|
||||
self.parameters = None
|
||||
self.q_value = {}
|
||||
self.atomic_weight_ratio = None
|
||||
|
|
@ -490,8 +491,8 @@ class SingleLevelBreitWigner(MultiLevelBreitWigner):
|
|||
"""
|
||||
|
||||
def __init__(self, target_spin, energy_min, energy_max, channel, scattering):
|
||||
super(SingleLevelBreitWigner, self).__init__(
|
||||
target_spin, energy_min, energy_max, channel, scattering)
|
||||
super().__init__(target_spin, energy_min, energy_max, channel,
|
||||
scattering)
|
||||
|
||||
# Set resonance reconstruction function
|
||||
if _reconstruct:
|
||||
|
|
@ -549,8 +550,8 @@ class ReichMoore(ResonanceRange):
|
|||
"""
|
||||
|
||||
def __init__(self, target_spin, energy_min, energy_max, channel, scattering):
|
||||
super(ReichMoore, self).__init__(
|
||||
target_spin, energy_min, energy_max, channel, scattering)
|
||||
super().__init__(target_spin, energy_min, energy_max, channel,
|
||||
scattering)
|
||||
self.parameters = None
|
||||
self.angle_distribution = False
|
||||
self.num_l_convergence = 0
|
||||
|
|
@ -724,8 +725,7 @@ class RMatrixLimited(ResonanceRange):
|
|||
"""
|
||||
|
||||
def __init__(self, energy_min, energy_max, particle_pairs, spin_groups):
|
||||
super(RMatrixLimited, self).__init__(0.0, energy_min, energy_max,
|
||||
None, None)
|
||||
super().__init__(0.0, energy_min, energy_max, None, None)
|
||||
self.reduced_width = False
|
||||
self.formalism = 3
|
||||
self.particle_pairs = particle_pairs
|
||||
|
|
@ -931,8 +931,7 @@ class Unresolved(ResonanceRange):
|
|||
"""
|
||||
|
||||
def __init__(self, target_spin, energy_min, energy_max, scatter):
|
||||
super(Unresolved, self).__init__(
|
||||
target_spin, energy_min, energy_max, None, scatter)
|
||||
super().__init__(target_spin, energy_min, energy_max, None, scatter)
|
||||
self.energies = None
|
||||
self.parameters = None
|
||||
self.add_to_background = False
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
from collections import Iterable
|
||||
from collections.abc import Iterable
|
||||
from difflib import get_close_matches
|
||||
from numbers import Real
|
||||
import itertools
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
|
|
@ -25,37 +26,37 @@ from openmc.stats import Discrete, Tabular
|
|||
_THERMAL_NAMES = {
|
||||
'c_Al27': ('al', 'al27'),
|
||||
'c_Be': ('be', 'be-metal'),
|
||||
'c_BeO': ('beo',),
|
||||
'c_BeO': ('beo'),
|
||||
'c_Be_in_BeO': ('bebeo', 'be-o', 'be/o'),
|
||||
'c_C6H6': ('benz', 'c6h6'),
|
||||
'c_C_in_SiC': ('csic',),
|
||||
'c_Ca_in_CaH2': ('cah',),
|
||||
'c_Ca_in_CaH2': ('cah'),
|
||||
'c_D_in_D2O': ('dd2o', 'hwtr', 'hw'),
|
||||
'c_Fe56': ('fe', 'fe56'),
|
||||
'c_Graphite': ('graph', 'grph', 'gr'),
|
||||
'c_H_in_CaH2': ('hcah2',),
|
||||
'c_H_in_CaH2': ('hcah2'),
|
||||
'c_H_in_CH2': ('hch2', 'poly', 'pol'),
|
||||
'c_H_in_CH4_liquid': ('lch4', 'lmeth'),
|
||||
'c_H_in_CH4_solid': ('sch4', 'smeth'),
|
||||
'c_H_in_H2O': ('hh2o', 'lwtr', 'lw'),
|
||||
'c_H_in_H2O_solid': ('hice',),
|
||||
'c_H_in_C5O2H8': ('lucite', 'c5o2h8'),
|
||||
'c_H_in_YH2': ('hyh2',),
|
||||
'c_H_in_YH2': ('hyh2'),
|
||||
'c_H_in_ZrH': ('hzrh', 'h-zr', 'h/zr', 'hzr'),
|
||||
'c_Mg24': ('mg', 'mg24'),
|
||||
'c_O_in_BeO': ('obeo', 'o-be', 'o/be'),
|
||||
'c_O_in_D2O': ('od2o',),
|
||||
'c_O_in_H2O_ice': ('oice',),
|
||||
'c_O_in_D2O': ('od2o'),
|
||||
'c_O_in_H2O_ice': ('oice'),
|
||||
'c_O_in_UO2': ('ouo2', 'o2-u', 'o2/u'),
|
||||
'c_ortho_D': ('orthod', 'dortho'),
|
||||
'c_ortho_H': ('orthoh', 'hortho'),
|
||||
'c_Si_in_SiC': ('sisic',),
|
||||
'c_Si_in_SiC': ('sisic'),
|
||||
'c_SiO2_alpha': ('sio2', 'sio2a'),
|
||||
'c_SiO2_beta': ('sio2b'),
|
||||
'c_para_D': ('parad', 'dpara'),
|
||||
'c_para_H': ('parah', 'hpara'),
|
||||
'c_U_in_UO2': ('uuo2', 'u-o2', 'u/o2'),
|
||||
'c_Y_in_YH2': ('yyh2',),
|
||||
'c_Y_in_YH2': ('yyh2'),
|
||||
'c_Zr_in_ZrH': ('zrzrh', 'zr-h', 'zr/h')
|
||||
}
|
||||
|
||||
|
|
@ -84,13 +85,25 @@ def get_thermal_name(name):
|
|||
# Make an educated guess?? This actually works well for
|
||||
# JEFF-3.2 which stupidly uses names like lw00.32t,
|
||||
# lw01.32t, etc. for different temperatures
|
||||
for proper_name, names in _THERMAL_NAMES.items():
|
||||
matches = get_close_matches(
|
||||
name.lower(), names, cutoff=0.5)
|
||||
if len(matches) > 0:
|
||||
warn('Thermal scattering material "{}" is not recognized. '
|
||||
'Assigning a name of {}.'.format(name, proper_name))
|
||||
return proper_name
|
||||
|
||||
# First, construct a list of all the values/keys in the names
|
||||
# dictionary
|
||||
all_names = itertools.chain(_THERMAL_NAMES.keys(),
|
||||
*_THERMAL_NAMES.values())
|
||||
|
||||
matches = get_close_matches(name, all_names, cutoff=0.5)
|
||||
if len(matches) > 0:
|
||||
# Figure out the key for the corresponding match
|
||||
match = matches[0]
|
||||
if match not in _THERMAL_NAMES:
|
||||
for key, value_list in _THERMAL_NAMES.items():
|
||||
if match in value_list:
|
||||
match = key
|
||||
break
|
||||
|
||||
warn('Thermal scattering material "{}" is not recognized. '
|
||||
'Assigning a name of {}.'.format(name, match))
|
||||
return match
|
||||
else:
|
||||
# OK, we give up. Just use the ACE name.
|
||||
warn('Thermal scattering material "{0}" is not recognized. '
|
||||
|
|
@ -245,7 +258,7 @@ class ThermalScattering(EqualityMixin):
|
|||
def temperatures(self):
|
||||
return ["{}K".format(int(round(kT / K_BOLTZMANN))) for kT in self.kTs]
|
||||
|
||||
def export_to_hdf5(self, path, mode='a'):
|
||||
def export_to_hdf5(self, path, mode='a', libver='earliest'):
|
||||
"""Export table to an HDF5 file.
|
||||
|
||||
Parameters
|
||||
|
|
@ -255,10 +268,13 @@ class ThermalScattering(EqualityMixin):
|
|||
mode : {'r', r+', 'w', 'x', 'a'}
|
||||
Mode that is used to open the HDF5 file. This is the second argument
|
||||
to the :class:`h5py.File` constructor.
|
||||
libver : {'earliest', 'latest'}
|
||||
Compatibility mode for the HDF5 file. 'latest' will produce files
|
||||
that are less backwards compatible but have performance benefits.
|
||||
|
||||
"""
|
||||
# Open file and write version
|
||||
f = h5py.File(path, mode, libver='latest')
|
||||
f = h5py.File(path, mode, libver=libver)
|
||||
f.attrs['filetype'] = np.string_('data_thermal')
|
||||
f.attrs['version'] = np.array(HDF5_VERSION)
|
||||
|
||||
|
|
@ -406,30 +422,27 @@ class ThermalScattering(EqualityMixin):
|
|||
# Cross section
|
||||
elastic_xs_type = elastic_group['xs'].attrs['type'].decode()
|
||||
if elastic_xs_type == 'Tabulated1D':
|
||||
table.elastic_xs[T] = \
|
||||
Tabulated1D.from_hdf5(elastic_group['xs'])
|
||||
table.elastic_xs[T] = Tabulated1D.from_hdf5(
|
||||
elastic_group['xs'])
|
||||
elif elastic_xs_type == 'bragg':
|
||||
table.elastic_xs[T] = \
|
||||
CoherentElastic.from_hdf5(elastic_group['xs'])
|
||||
table.elastic_xs[T] = CoherentElastic.from_hdf5(
|
||||
elastic_group['xs'])
|
||||
|
||||
# Angular distribution
|
||||
if 'mu_out' in elastic_group:
|
||||
table.elastic_mu_out[T] = \
|
||||
elastic_group['mu_out'].value
|
||||
table.elastic_mu_out[T] = elastic_group['mu_out'].value
|
||||
|
||||
# Read thermal inelastic scattering
|
||||
if 'inelastic' in Tgroup:
|
||||
inelastic_group = Tgroup['inelastic']
|
||||
table.inelastic_xs[T] = \
|
||||
Tabulated1D.from_hdf5(inelastic_group['xs'])
|
||||
table.inelastic_xs[T] = Tabulated1D.from_hdf5(
|
||||
inelastic_group['xs'])
|
||||
if table.secondary_mode in ('equal', 'skewed'):
|
||||
table.inelastic_e_out[T] = \
|
||||
inelastic_group['energy_out']
|
||||
table.inelastic_mu_out[T] = \
|
||||
inelastic_group['mu_out']
|
||||
table.inelastic_e_out[T] = inelastic_group['energy_out'].value
|
||||
table.inelastic_mu_out[T] = inelastic_group['mu_out'].value
|
||||
elif table.secondary_mode == 'continuous':
|
||||
table.inelastic_dist[T] = \
|
||||
AngleEnergy.from_hdf5(inelastic_group)
|
||||
table.inelastic_dist[T] = AngleEnergy.from_hdf5(
|
||||
inelastic_group)
|
||||
|
||||
return table
|
||||
|
||||
|
|
@ -611,10 +624,7 @@ class ThermalScattering(EqualityMixin):
|
|||
Thermal scattering data
|
||||
|
||||
"""
|
||||
# Create temporary directory -- it would be preferable to use
|
||||
# TemporaryDirectory(), but it is only available in Python 3.2
|
||||
tmpdir = tempfile.mkdtemp()
|
||||
try:
|
||||
with tempfile.TemporaryDirectory() as tmpdir:
|
||||
# Run NJOY to create an ACE library
|
||||
ace_file = os.path.join(tmpdir, 'ace')
|
||||
xsdir_file = os.path.join(tmpdir, 'xsdir')
|
||||
|
|
@ -626,8 +636,5 @@ class ThermalScattering(EqualityMixin):
|
|||
data = cls.from_ace(lib.tables[0])
|
||||
for table in lib.tables[1:]:
|
||||
data.add_temperature_from_ace(table)
|
||||
finally:
|
||||
# Get rid of temporary files
|
||||
shutil.rmtree(tmpdir)
|
||||
|
||||
return data
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from collections import Iterable
|
||||
from collections.abc import Iterable
|
||||
from numbers import Integral, Real
|
||||
|
||||
import numpy as np
|
||||
|
|
|
|||
24
openmc/deplete/__init__.py
Normal file
24
openmc/deplete/__init__.py
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
"""
|
||||
openmc.deplete
|
||||
==============
|
||||
|
||||
A depletion front-end tool.
|
||||
"""
|
||||
|
||||
from .dummy_comm import DummyCommunicator
|
||||
try:
|
||||
from mpi4py import MPI
|
||||
comm = MPI.COMM_WORLD
|
||||
have_mpi = True
|
||||
except ImportError:
|
||||
comm = DummyCommunicator()
|
||||
have_mpi = False
|
||||
|
||||
from .nuclide import *
|
||||
from .chain import *
|
||||
from .operator import *
|
||||
from .reaction_rates import *
|
||||
from .abc import *
|
||||
from .results import *
|
||||
from .results_list import *
|
||||
from .integrator import *
|
||||
142
openmc/deplete/abc.py
Normal file
142
openmc/deplete/abc.py
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
"""function module.
|
||||
|
||||
This module contains the Operator class, which is then passed to an integrator
|
||||
to run a full depletion simulation.
|
||||
"""
|
||||
|
||||
from collections import namedtuple
|
||||
import os
|
||||
from pathlib import Path
|
||||
from abc import ABCMeta, abstractmethod
|
||||
|
||||
from .chain import Chain
|
||||
|
||||
OperatorResult = namedtuple('OperatorResult', ['k', 'rates'])
|
||||
OperatorResult.__doc__ = """\
|
||||
Result of applying transport operator
|
||||
|
||||
Parameters
|
||||
----------
|
||||
k : float
|
||||
Resulting eigenvalue
|
||||
rates : openmc.deplete.ReactionRates
|
||||
Resulting reaction rates
|
||||
|
||||
"""
|
||||
try:
|
||||
OperatorResult.k.__doc__ = None
|
||||
OperatorResult.rates.__doc__ = None
|
||||
except AttributeError:
|
||||
# Can't set __doc__ on properties on Python 3.4
|
||||
pass
|
||||
|
||||
|
||||
class TransportOperator(metaclass=ABCMeta):
|
||||
"""Abstract class defining a transport operator
|
||||
|
||||
Each depletion integrator is written to work with a generic transport
|
||||
operator that takes a vector of material compositions and returns an
|
||||
eigenvalue and reaction rates. This abstract class sets the requirements for
|
||||
such a transport operator. Users should instantiate
|
||||
:class:`openmc.deplete.Operator` rather than this class.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
chain_file : str, optional
|
||||
Path to the depletion chain XML file. Defaults to the
|
||||
:envvar:`OPENMC_DEPLETE_CHAIN` environment variable if it exists.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
dilute_initial : float
|
||||
Initial atom density to add for nuclides that are zero in initial
|
||||
condition to ensure they exist in the decay chain. Only done for
|
||||
nuclides with reaction rates. Defaults to 1.0e3.
|
||||
|
||||
"""
|
||||
def __init__(self, chain_file=None):
|
||||
self.dilute_initial = 1.0e3
|
||||
self.output_dir = '.'
|
||||
|
||||
# Read depletion chain
|
||||
if chain_file is None:
|
||||
chain_file = os.environ.get("OPENMC_DEPLETE_CHAIN", None)
|
||||
if chain_file is None:
|
||||
raise IOError("No chain specified, either manually or in "
|
||||
"environment variable OPENMC_DEPLETE_CHAIN.")
|
||||
self.chain = Chain.from_xml(chain_file)
|
||||
|
||||
@abstractmethod
|
||||
def __call__(self, vec, print_out=True):
|
||||
"""Runs a simulation.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
vec : list of numpy.ndarray
|
||||
Total atoms to be used in function.
|
||||
print_out : bool, optional
|
||||
Whether or not to print out time.
|
||||
|
||||
Returns
|
||||
-------
|
||||
openmc.deplete.OperatorResult
|
||||
Eigenvalue and reaction rates resulting from transport operator
|
||||
|
||||
"""
|
||||
pass
|
||||
|
||||
def __enter__(self):
|
||||
# Save current directory and move to specific output directory
|
||||
self._orig_dir = os.getcwd()
|
||||
if not self.output_dir.exists():
|
||||
self.output_dir.mkdir() # exist_ok parameter is 3.5+
|
||||
|
||||
# In Python 3.6+, chdir accepts a Path directly
|
||||
os.chdir(str(self.output_dir))
|
||||
|
||||
return self.initial_condition()
|
||||
|
||||
def __exit__(self, exc_type, exc_value, traceback):
|
||||
self.finalize()
|
||||
os.chdir(self._orig_dir)
|
||||
|
||||
@property
|
||||
def output_dir(self):
|
||||
return self._output_dir
|
||||
|
||||
@output_dir.setter
|
||||
def output_dir(self, output_dir):
|
||||
self._output_dir = Path(output_dir)
|
||||
|
||||
@abstractmethod
|
||||
def initial_condition(self):
|
||||
"""Performs final setup and returns initial condition.
|
||||
|
||||
Returns
|
||||
-------
|
||||
list of numpy.ndarray
|
||||
Total density for initial conditions.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_results_info(self):
|
||||
"""Returns volume list, cell lists, and nuc lists.
|
||||
|
||||
Returns
|
||||
-------
|
||||
volume : list of float
|
||||
Volumes corresponding to materials in burn_list
|
||||
nuc_list : list of str
|
||||
A list of all nuclide names. Used for sorting the simulation.
|
||||
burn_list : list of int
|
||||
A list of all cell IDs to be burned. Used for sorting the simulation.
|
||||
full_burn_list : list of int
|
||||
All burnable materials in the geometry.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
def finalize(self):
|
||||
pass
|
||||
214
openmc/deplete/atom_number.py
Normal file
214
openmc/deplete/atom_number.py
Normal file
|
|
@ -0,0 +1,214 @@
|
|||
"""AtomNumber module.
|
||||
|
||||
An ndarray to store atom densities with string, integer, or slice indexing.
|
||||
"""
|
||||
from collections import OrderedDict
|
||||
|
||||
import numpy as np
|
||||
|
||||
|
||||
class AtomNumber(object):
|
||||
"""Stores local material compositions (atoms of each nuclide).
|
||||
|
||||
Parameters
|
||||
----------
|
||||
local_mats : list of str
|
||||
Material IDs
|
||||
nuclides : list of str
|
||||
Nuclides to be tracked
|
||||
volume : dict
|
||||
Volume of each material in [cm^3]
|
||||
n_nuc_burn : int
|
||||
Number of nuclides to be burned.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
index_mat : dict
|
||||
A dictionary mapping material ID as string to index.
|
||||
index_nuc : dict
|
||||
A dictionary mapping nuclide name to index.
|
||||
volume : numpy.ndarray
|
||||
Volume of each material in [cm^3]. If a volume is not found, it defaults
|
||||
to 1 so that reading density still works correctly.
|
||||
number : numpy.ndarray
|
||||
Array storing total atoms for each material/nuclide
|
||||
materials : list of str
|
||||
Material IDs as strings
|
||||
nuclides : list of str
|
||||
All nuclide names
|
||||
burnable_nuclides : list of str
|
||||
Burnable nuclides names. Used for sorting the simulation.
|
||||
n_nuc_burn : int
|
||||
Number of burnable nuclides.
|
||||
n_nuc : int
|
||||
Number of nuclides.
|
||||
|
||||
"""
|
||||
def __init__(self, local_mats, nuclides, volume, n_nuc_burn):
|
||||
self.index_mat = OrderedDict((mat, i) for i, mat in enumerate(local_mats))
|
||||
self.index_nuc = OrderedDict((nuc, i) for i, nuc in enumerate(nuclides))
|
||||
|
||||
self.volume = np.ones(len(local_mats))
|
||||
for mat, val in volume.items():
|
||||
if mat in self.index_mat:
|
||||
ind = self.index_mat[mat]
|
||||
self.volume[ind] = val
|
||||
|
||||
self.n_nuc_burn = n_nuc_burn
|
||||
|
||||
self.number = np.zeros((len(local_mats), len(nuclides)))
|
||||
|
||||
def __getitem__(self, pos):
|
||||
"""Retrieves total atom number from AtomNumber.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
pos : tuple
|
||||
A two-length tuple containing a material index and a nuc index.
|
||||
These indexes can be strings (which get converted to integers via
|
||||
the dictionaries), integers used directly, or slices.
|
||||
|
||||
Returns
|
||||
-------
|
||||
numpy.ndarray
|
||||
The value indexed from self.number.
|
||||
"""
|
||||
|
||||
mat, nuc = pos
|
||||
if isinstance(mat, str):
|
||||
mat = self.index_mat[mat]
|
||||
if isinstance(nuc, str):
|
||||
nuc = self.index_nuc[nuc]
|
||||
|
||||
return self.number[mat, nuc]
|
||||
|
||||
def __setitem__(self, pos, val):
|
||||
"""Sets total atom number into AtomNumber.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
pos : tuple
|
||||
A two-length tuple containing a material index and a nuc index.
|
||||
These indexes can be strings (which get converted to integers via
|
||||
the dictionaries), integers used directly, or slices.
|
||||
val : float
|
||||
The value [atom] to set the array to.
|
||||
|
||||
"""
|
||||
mat, nuc = pos
|
||||
if isinstance(mat, str):
|
||||
mat = self.index_mat[mat]
|
||||
if isinstance(nuc, str):
|
||||
nuc = self.index_nuc[nuc]
|
||||
|
||||
self.number[mat, nuc] = val
|
||||
|
||||
@property
|
||||
def materials(self):
|
||||
return self.index_mat.keys()
|
||||
|
||||
@property
|
||||
def nuclides(self):
|
||||
return self.index_nuc.keys()
|
||||
|
||||
@property
|
||||
def n_nuc(self):
|
||||
return len(self.index_nuc)
|
||||
|
||||
@property
|
||||
def burnable_nuclides(self):
|
||||
return [nuc for nuc, ind in self.index_nuc.items()
|
||||
if ind < self.n_nuc_burn]
|
||||
|
||||
def get_atom_density(self, mat, nuc):
|
||||
"""Accesses atom density instead of total number.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
mat : str, int or slice
|
||||
Material index.
|
||||
nuc : str, int or slice
|
||||
Nuclide index.
|
||||
|
||||
Returns
|
||||
-------
|
||||
numpy.ndarray
|
||||
Density in [atom/cm^3]
|
||||
|
||||
"""
|
||||
if isinstance(mat, str):
|
||||
mat = self.index_mat[mat]
|
||||
if isinstance(nuc, str):
|
||||
nuc = self.index_nuc[nuc]
|
||||
|
||||
return self[mat, nuc] / self.volume[mat]
|
||||
|
||||
def set_atom_density(self, mat, nuc, val):
|
||||
"""Sets atom density instead of total number.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
mat : str, int or slice
|
||||
Material index.
|
||||
nuc : str, int or slice
|
||||
Nuclide index.
|
||||
val : numpy.ndarray
|
||||
Array of densities to set in [atom/cm^3]
|
||||
|
||||
"""
|
||||
if isinstance(mat, str):
|
||||
mat = self.index_mat[mat]
|
||||
if isinstance(nuc, str):
|
||||
nuc = self.index_nuc[nuc]
|
||||
|
||||
self[mat, nuc] = val * self.volume[mat]
|
||||
|
||||
def get_mat_slice(self, mat):
|
||||
"""Gets atom quantity indexed by mats for all burned nuclides
|
||||
|
||||
Parameters
|
||||
----------
|
||||
mat : str, int or slice
|
||||
Material index.
|
||||
|
||||
Returns
|
||||
-------
|
||||
numpy.ndarray
|
||||
The slice requested in [atom].
|
||||
|
||||
"""
|
||||
if isinstance(mat, str):
|
||||
mat = self.index_mat[mat]
|
||||
|
||||
return self[mat, :self.n_nuc_burn]
|
||||
|
||||
def set_mat_slice(self, mat, val):
|
||||
"""Sets atom quantity indexed by mats for all burned nuclides
|
||||
|
||||
Parameters
|
||||
----------
|
||||
mat : str, int or slice
|
||||
Material index.
|
||||
val : numpy.ndarray
|
||||
The slice to set in [atom]
|
||||
|
||||
"""
|
||||
if isinstance(mat, str):
|
||||
mat = self.index_mat[mat]
|
||||
|
||||
self[mat, :self.n_nuc_burn] = val
|
||||
|
||||
def set_density(self, total_density):
|
||||
"""Sets density.
|
||||
|
||||
Sets the density in the exact same order as total_density_list outputs,
|
||||
allowing for internal consistency
|
||||
|
||||
Parameters
|
||||
----------
|
||||
total_density : list of numpy.ndarray
|
||||
Total atoms.
|
||||
|
||||
"""
|
||||
for i, density_slice in enumerate(total_density):
|
||||
self.set_mat_slice(i, density_slice)
|
||||
440
openmc/deplete/chain.py
Normal file
440
openmc/deplete/chain.py
Normal file
|
|
@ -0,0 +1,440 @@
|
|||
"""chain module.
|
||||
|
||||
This module contains information about a depletion chain. A depletion chain is
|
||||
loaded from an .xml file and all the nuclides are linked together.
|
||||
"""
|
||||
|
||||
from collections import OrderedDict, defaultdict
|
||||
from io import StringIO
|
||||
from itertools import chain
|
||||
import math
|
||||
import re
|
||||
import os
|
||||
|
||||
# Try to use lxml if it is available. It preserves the order of attributes and
|
||||
# provides a pretty-printer by default. If not available, use OpenMC function to
|
||||
# pretty print.
|
||||
try:
|
||||
import lxml.etree as ET
|
||||
_have_lxml = True
|
||||
except ImportError:
|
||||
import xml.etree.ElementTree as ET
|
||||
_have_lxml = False
|
||||
import scipy.sparse as sp
|
||||
|
||||
import openmc.data
|
||||
from openmc.clean_xml import clean_xml_indentation
|
||||
from .nuclide import Nuclide, DecayTuple, ReactionTuple
|
||||
|
||||
|
||||
# tuple of (reaction name, possible MT values, (dA, dZ)) where dA is the change
|
||||
# in the mass number and dZ is the change in the atomic number
|
||||
_REACTIONS = [
|
||||
('(n,2n)', set(chain([16], range(875, 892))), (-1, 0)),
|
||||
('(n,3n)', {17}, (-2, 0)),
|
||||
('(n,4n)', {37}, (-3, 0)),
|
||||
('(n,gamma)', {102}, (1, 0)),
|
||||
('(n,p)', set(chain([103], range(600, 650))), (0, -1)),
|
||||
('(n,a)', set(chain([107], range(800, 850))), (-3, -2))
|
||||
]
|
||||
|
||||
|
||||
def replace_missing(product, decay_data):
|
||||
"""Replace missing product with suitable decay daughter.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
product : str
|
||||
Name of product in GND format, e.g. 'Y86_m1'.
|
||||
decay_data : dict
|
||||
Dictionary of decay data
|
||||
|
||||
Returns
|
||||
-------
|
||||
product : str
|
||||
Replacement for missing product in GND format.
|
||||
|
||||
"""
|
||||
# Determine atomic number, mass number, and metastable state
|
||||
Z, A, state = openmc.data.zam(product)
|
||||
symbol = openmc.data.ATOMIC_SYMBOL[Z]
|
||||
|
||||
# Replace neutron with proton
|
||||
if Z == 0 and A == 1:
|
||||
return 'H1'
|
||||
|
||||
# First check if ground state is available
|
||||
if state:
|
||||
product = '{}{}'.format(symbol, A)
|
||||
|
||||
# Find isotope with longest half-life
|
||||
half_life = 0.0
|
||||
for nuclide, data in decay_data.items():
|
||||
m = re.match(r'{}(\d+)(?:_m\d+)?'.format(symbol), nuclide)
|
||||
if m:
|
||||
# If we find a stable nuclide, stop search
|
||||
if data.nuclide['stable']:
|
||||
mass_longest_lived = int(m.group(1))
|
||||
break
|
||||
if data.half_life.nominal_value > half_life:
|
||||
mass_longest_lived = int(m.group(1))
|
||||
half_life = data.half_life.nominal_value
|
||||
|
||||
# If mass number of longest-lived isotope is less than that of missing
|
||||
# product, assume it undergoes beta-. Otherwise assume beta+.
|
||||
beta_minus = (mass_longest_lived < A)
|
||||
|
||||
# Iterate until we find an existing nuclide
|
||||
while product not in decay_data:
|
||||
if Z > 98:
|
||||
Z -= 2
|
||||
A -= 4
|
||||
else:
|
||||
if beta_minus:
|
||||
Z += 1
|
||||
else:
|
||||
Z -= 1
|
||||
product = '{}{}'.format(openmc.data.ATOMIC_SYMBOL[Z], A)
|
||||
|
||||
return product
|
||||
|
||||
|
||||
class Chain(object):
|
||||
"""Full representation of a depletion chain.
|
||||
|
||||
A depletion chain can be created by using the :meth:`from_endf` method which
|
||||
requires a list of ENDF incident neutron, decay, and neutron fission product
|
||||
yield sublibrary files. The depletion chain used during a depletion
|
||||
simulation is indicated by either an argument to
|
||||
:class:`openmc.deplete.Operator` or through the
|
||||
:envvar:`OPENMC_DEPLETE_CHAIN` environment variable.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
nuclides : list of openmc.deplete.Nuclide
|
||||
Nuclides present in the chain.
|
||||
reactions : list of str
|
||||
Reactions that are tracked in the depletion chain
|
||||
nuclide_dict : OrderedDict of str to int
|
||||
Maps a nuclide name to an index in nuclides.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.nuclides = []
|
||||
self.reactions = []
|
||||
self.nuclide_dict = OrderedDict()
|
||||
|
||||
def __contains__(self, nuclide):
|
||||
return nuclide in self.nuclide_dict
|
||||
|
||||
def __getitem__(self, name):
|
||||
"""Get a Nuclide by name."""
|
||||
return self.nuclides[self.nuclide_dict[name]]
|
||||
|
||||
def __len__(self):
|
||||
"""Number of nuclides in chain."""
|
||||
return len(self.nuclides)
|
||||
|
||||
@classmethod
|
||||
def from_endf(cls, decay_files, fpy_files, neutron_files):
|
||||
"""Create a depletion chain from ENDF files.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
decay_files : list of str
|
||||
List of ENDF decay sub-library files
|
||||
fpy_files : list of str
|
||||
List of ENDF neutron-induced fission product yield sub-library files
|
||||
neutron_files : list of str
|
||||
List of ENDF neutron reaction sub-library files
|
||||
|
||||
"""
|
||||
chain = cls()
|
||||
|
||||
# Create dictionary mapping target to filename
|
||||
print('Processing neutron sub-library files...')
|
||||
reactions = {}
|
||||
for f in neutron_files:
|
||||
evaluation = openmc.data.endf.Evaluation(f)
|
||||
name = evaluation.gnd_name
|
||||
reactions[name] = {}
|
||||
for mf, mt, nc, mod in evaluation.reaction_list:
|
||||
if mf == 3:
|
||||
file_obj = StringIO(evaluation.section[3, mt])
|
||||
openmc.data.endf.get_head_record(file_obj)
|
||||
q_value = openmc.data.endf.get_cont_record(file_obj)[1]
|
||||
reactions[name][mt] = q_value
|
||||
|
||||
# Determine what decay and FPY nuclides are available
|
||||
print('Processing decay sub-library files...')
|
||||
decay_data = {}
|
||||
for f in decay_files:
|
||||
data = openmc.data.Decay(f)
|
||||
# Skip decay data for neutron itself
|
||||
if data.nuclide['atomic_number'] == 0:
|
||||
continue
|
||||
decay_data[data.nuclide['name']] = data
|
||||
|
||||
print('Processing fission product yield sub-library files...')
|
||||
fpy_data = {}
|
||||
for f in fpy_files:
|
||||
data = openmc.data.FissionProductYields(f)
|
||||
fpy_data[data.nuclide['name']] = data
|
||||
|
||||
print('Creating depletion_chain...')
|
||||
missing_daughter = []
|
||||
missing_rx_product = []
|
||||
missing_fpy = []
|
||||
missing_fp = []
|
||||
|
||||
for idx, parent in enumerate(sorted(decay_data, key=openmc.data.zam)):
|
||||
data = decay_data[parent]
|
||||
|
||||
nuclide = Nuclide()
|
||||
nuclide.name = parent
|
||||
|
||||
chain.nuclides.append(nuclide)
|
||||
chain.nuclide_dict[parent] = idx
|
||||
|
||||
if not data.nuclide['stable'] and data.half_life.nominal_value != 0.0:
|
||||
nuclide.half_life = data.half_life.nominal_value
|
||||
nuclide.decay_energy = sum(E.nominal_value for E in
|
||||
data.average_energies.values())
|
||||
sum_br = 0.0
|
||||
for i, mode in enumerate(data.modes):
|
||||
type_ = ','.join(mode.modes)
|
||||
if mode.daughter in decay_data:
|
||||
target = mode.daughter
|
||||
else:
|
||||
print('missing {} {} {}'.format(parent, ','.join(mode.modes), mode.daughter))
|
||||
target = replace_missing(mode.daughter, decay_data)
|
||||
|
||||
# Write branching ratio, taking care to ensure sum is unity
|
||||
br = mode.branching_ratio.nominal_value
|
||||
sum_br += br
|
||||
if i == len(data.modes) - 1 and sum_br != 1.0:
|
||||
br = 1.0 - sum(m.branching_ratio.nominal_value
|
||||
for m in data.modes[:-1])
|
||||
|
||||
# Append decay mode
|
||||
nuclide.decay_modes.append(DecayTuple(type_, target, br))
|
||||
|
||||
if parent in reactions:
|
||||
reactions_available = set(reactions[parent].keys())
|
||||
for name, mts, changes in _REACTIONS:
|
||||
if mts & reactions_available:
|
||||
delta_A, delta_Z = changes
|
||||
A = data.nuclide['mass_number'] + delta_A
|
||||
Z = data.nuclide['atomic_number'] + delta_Z
|
||||
daughter = '{}{}'.format(openmc.data.ATOMIC_SYMBOL[Z], A)
|
||||
|
||||
if name not in chain.reactions:
|
||||
chain.reactions.append(name)
|
||||
|
||||
if daughter not in decay_data:
|
||||
missing_rx_product.append((parent, name, daughter))
|
||||
|
||||
# Store Q value
|
||||
for mt in sorted(mts):
|
||||
if mt in reactions[parent]:
|
||||
q_value = reactions[parent][mt]
|
||||
break
|
||||
else:
|
||||
q_value = 0.0
|
||||
|
||||
nuclide.reactions.append(ReactionTuple(
|
||||
name, daughter, q_value, 1.0))
|
||||
|
||||
if any(mt in reactions_available for mt in [18, 19, 20, 21, 38]):
|
||||
if parent in fpy_data:
|
||||
q_value = reactions[parent][18]
|
||||
nuclide.reactions.append(
|
||||
ReactionTuple('fission', 0, q_value, 1.0))
|
||||
|
||||
if 'fission' not in chain.reactions:
|
||||
chain.reactions.append('fission')
|
||||
else:
|
||||
missing_fpy.append(parent)
|
||||
|
||||
if parent in fpy_data:
|
||||
fpy = fpy_data[parent]
|
||||
|
||||
if fpy.energies is not None:
|
||||
nuclide.yield_energies = fpy.energies
|
||||
else:
|
||||
nuclide.yield_energies = [0.0]
|
||||
|
||||
for E, table in zip(nuclide.yield_energies, fpy.independent):
|
||||
yield_replace = 0.0
|
||||
yields = defaultdict(float)
|
||||
for product, y in table.items():
|
||||
# Handle fission products that have no decay data available
|
||||
if product not in decay_data:
|
||||
daughter = replace_missing(product, decay_data)
|
||||
product = daughter
|
||||
yield_replace += y.nominal_value
|
||||
|
||||
yields[product] += y.nominal_value
|
||||
|
||||
if yield_replace > 0.0:
|
||||
missing_fp.append((parent, E, yield_replace))
|
||||
|
||||
nuclide.yield_data[E] = []
|
||||
for k in sorted(yields, key=openmc.data.zam):
|
||||
nuclide.yield_data[E].append((k, yields[k]))
|
||||
|
||||
# Display warnings
|
||||
if missing_daughter:
|
||||
print('The following decay modes have daughters with no decay data:')
|
||||
for mode in missing_daughter:
|
||||
print(' {}'.format(mode))
|
||||
print('')
|
||||
|
||||
if missing_rx_product:
|
||||
print('The following reaction products have no decay data:')
|
||||
for vals in missing_rx_product:
|
||||
print('{} {} -> {}'.format(*vals))
|
||||
print('')
|
||||
|
||||
if missing_fpy:
|
||||
print('The following fissionable nuclides have no fission product yields:')
|
||||
for parent in missing_fpy:
|
||||
print(' ' + parent)
|
||||
print('')
|
||||
|
||||
if missing_fp:
|
||||
print('The following nuclides have fission products with no decay data:')
|
||||
for vals in missing_fp:
|
||||
print(' {}, E={} eV (total yield={})'.format(*vals))
|
||||
|
||||
return chain
|
||||
|
||||
@classmethod
|
||||
def from_xml(cls, filename):
|
||||
"""Reads a depletion chain XML file.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
filename : str
|
||||
The path to the depletion chain XML file.
|
||||
|
||||
"""
|
||||
chain = cls()
|
||||
|
||||
# Load XML tree
|
||||
root = ET.parse(str(filename))
|
||||
|
||||
for i, nuclide_elem in enumerate(root.findall('nuclide')):
|
||||
nuc = Nuclide.from_xml(nuclide_elem)
|
||||
chain.nuclide_dict[nuc.name] = i
|
||||
|
||||
# Check for reaction paths
|
||||
for rx in nuc.reactions:
|
||||
if rx.type not in chain.reactions:
|
||||
chain.reactions.append(rx.type)
|
||||
|
||||
chain.nuclides.append(nuc)
|
||||
|
||||
return chain
|
||||
|
||||
def export_to_xml(self, filename):
|
||||
"""Writes a depletion chain XML file.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
filename : str
|
||||
The path to the depletion chain XML file.
|
||||
|
||||
"""
|
||||
|
||||
root_elem = ET.Element('depletion_chain')
|
||||
for nuclide in self.nuclides:
|
||||
root_elem.append(nuclide.to_xml_element())
|
||||
|
||||
tree = ET.ElementTree(root_elem)
|
||||
if _have_lxml:
|
||||
tree.write(str(filename), encoding='utf-8', pretty_print=True)
|
||||
else:
|
||||
clean_xml_indentation(root_elem)
|
||||
tree.write(str(filename), encoding='utf-8')
|
||||
|
||||
def form_matrix(self, rates):
|
||||
"""Forms depletion matrix.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
rates : numpy.ndarray
|
||||
2D array indexed by (nuclide, reaction)
|
||||
|
||||
Returns
|
||||
-------
|
||||
scipy.sparse.csr_matrix
|
||||
Sparse matrix representing depletion.
|
||||
|
||||
"""
|
||||
matrix = defaultdict(float)
|
||||
reactions = set()
|
||||
|
||||
for i, nuc in enumerate(self.nuclides):
|
||||
|
||||
if nuc.n_decay_modes != 0:
|
||||
# Decay paths
|
||||
# Loss
|
||||
decay_constant = math.log(2) / nuc.half_life
|
||||
|
||||
if decay_constant != 0.0:
|
||||
matrix[i, i] -= decay_constant
|
||||
|
||||
# Gain
|
||||
for _, target, branching_ratio in nuc.decay_modes:
|
||||
# Allow for total annihilation for debug purposes
|
||||
if target != 'Nothing':
|
||||
branch_val = branching_ratio * decay_constant
|
||||
|
||||
if branch_val != 0.0:
|
||||
k = self.nuclide_dict[target]
|
||||
matrix[k, i] += branch_val
|
||||
|
||||
if nuc.name in rates.index_nuc:
|
||||
# Extract all reactions for this nuclide in this cell
|
||||
nuc_ind = rates.index_nuc[nuc.name]
|
||||
nuc_rates = rates[nuc_ind, :]
|
||||
|
||||
for r_type, target, _, br in nuc.reactions:
|
||||
# Extract reaction index, and then final reaction rate
|
||||
r_id = rates.index_rx[r_type]
|
||||
path_rate = nuc_rates[r_id]
|
||||
|
||||
# Loss term -- make sure we only count loss once for
|
||||
# reactions with branching ratios
|
||||
if r_type not in reactions:
|
||||
reactions.add(r_type)
|
||||
if path_rate != 0.0:
|
||||
matrix[i, i] -= path_rate
|
||||
|
||||
# Gain term; allow for total annihilation for debug purposes
|
||||
if target != 'Nothing':
|
||||
if r_type != 'fission':
|
||||
if path_rate != 0.0:
|
||||
k = self.nuclide_dict[target]
|
||||
matrix[k, i] += path_rate * br
|
||||
else:
|
||||
# Assume that we should always use thermal fission
|
||||
# yields. At some point it would be nice to account
|
||||
# for the energy-dependence..
|
||||
energy, data = sorted(nuc.yield_data.items())[0]
|
||||
for product, y in data:
|
||||
yield_val = y * path_rate
|
||||
if yield_val != 0.0:
|
||||
k = self.nuclide_dict[product]
|
||||
matrix[k, i] += yield_val
|
||||
|
||||
# Clear set of reactions
|
||||
reactions.clear()
|
||||
|
||||
# Use DOK matrix as intermediate representation, then convert to CSR and return
|
||||
n = len(self)
|
||||
matrix_dok = sp.dok_matrix((n, n))
|
||||
dict.update(matrix_dok, matrix)
|
||||
return matrix_dok.tocsr()
|
||||
27
openmc/deplete/dummy_comm.py
Normal file
27
openmc/deplete/dummy_comm.py
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
class DummyCommunicator(object):
|
||||
rank = 0
|
||||
size = 1
|
||||
|
||||
def allgather(self, sendobj):
|
||||
return [sendobj]
|
||||
|
||||
def allreduce(self, sendobj, op=None):
|
||||
return sendobj
|
||||
|
||||
def barrier(self):
|
||||
pass
|
||||
|
||||
def bcast(self, obj, root=0):
|
||||
return obj
|
||||
|
||||
def gather(self, sendobj, root=0):
|
||||
return [sendobj]
|
||||
|
||||
def py2f(self):
|
||||
return 0
|
||||
|
||||
def reduce(self, sendobj, op=None, root=0):
|
||||
return sendobj
|
||||
|
||||
def scatter(self, sendobj, root=0):
|
||||
return sendobj[0]
|
||||
10
openmc/deplete/integrator/__init__.py
Normal file
10
openmc/deplete/integrator/__init__.py
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
"""
|
||||
Integrator
|
||||
===========
|
||||
|
||||
The integrator subcomponents.
|
||||
"""
|
||||
|
||||
from .cecm import *
|
||||
from .cram import *
|
||||
from .predictor import *
|
||||
78
openmc/deplete/integrator/cecm.py
Normal file
78
openmc/deplete/integrator/cecm.py
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
"""The CE/CM integrator."""
|
||||
|
||||
import copy
|
||||
from collections.abc import Iterable
|
||||
|
||||
from .cram import deplete
|
||||
from ..results import Results
|
||||
|
||||
|
||||
def cecm(operator, timesteps, power, print_out=True):
|
||||
r"""Deplete using the CE/CM algorithm.
|
||||
|
||||
Implements the second order `CE/CM predictor-corrector algorithm
|
||||
<https://doi.org/10.13182/NSE14-92>`_. This algorithm is mathematically
|
||||
defined as:
|
||||
|
||||
.. math::
|
||||
y' &= A(y, t) y(t)
|
||||
|
||||
A_p &= A(y_n, t_n)
|
||||
|
||||
y_m &= \text{expm}(A_p h/2) y_n
|
||||
|
||||
A_c &= A(y_m, t_n + h/2)
|
||||
|
||||
y_{n+1} &= \text{expm}(A_c h) y_n
|
||||
|
||||
Parameters
|
||||
----------
|
||||
operator : openmc.deplete.TransportOperator
|
||||
The operator object to simulate on.
|
||||
timesteps : iterable of float
|
||||
Array of timesteps in units of [s]. Note that values are not cumulative.
|
||||
power : float or iterable of float
|
||||
Power of the reactor in [W]. A single value indicates that the power is
|
||||
constant over all timesteps. An iterable indicates potentially different
|
||||
power levels for each timestep. For a 2D problem, the power can be given
|
||||
in [W/cm] as long as the "volume" assigned to a depletion material is
|
||||
actually an area in [cm^2].
|
||||
print_out : bool, optional
|
||||
Whether or not to print out time.
|
||||
|
||||
"""
|
||||
if not isinstance(power, Iterable):
|
||||
power = [power]*len(timesteps)
|
||||
|
||||
# Generate initial conditions
|
||||
with operator as vec:
|
||||
chain = operator.chain
|
||||
t = 0.0
|
||||
for i, (dt, p) in enumerate(zip(timesteps, power)):
|
||||
# Get beginning-of-timestep reaction rates
|
||||
x = [copy.deepcopy(vec)]
|
||||
op_results = [operator(x[0], p)]
|
||||
|
||||
# Deplete for first half of timestep
|
||||
x_middle = deplete(chain, x[0], op_results[0], dt/2, print_out)
|
||||
|
||||
# Get middle-of-timestep reaction rates
|
||||
x.append(x_middle)
|
||||
op_results.append(operator(x_middle, p))
|
||||
|
||||
# Deplete for full timestep using beginning-of-step materials
|
||||
x_end = deplete(chain, x[0], op_results[1], dt, print_out)
|
||||
|
||||
# Create results, write to disk
|
||||
Results.save(operator, x, op_results, [t, t + dt], i)
|
||||
|
||||
# Advance time, update vector
|
||||
t += dt
|
||||
vec = copy.deepcopy(x_end)
|
||||
|
||||
# Perform one last simulation
|
||||
x = [copy.deepcopy(vec)]
|
||||
op_results = [operator(x[0], power[-1])]
|
||||
|
||||
# Create results, write to disk
|
||||
Results.save(operator, x, op_results, [t, t], len(timesteps))
|
||||
227
openmc/deplete/integrator/cram.py
Normal file
227
openmc/deplete/integrator/cram.py
Normal file
|
|
@ -0,0 +1,227 @@
|
|||
"""Chebyshev Rational Approximation Method module
|
||||
|
||||
Implements two different forms of CRAM for use in openmc.deplete.
|
||||
"""
|
||||
|
||||
from itertools import repeat
|
||||
from multiprocessing import Pool
|
||||
import time
|
||||
|
||||
import numpy as np
|
||||
import scipy.sparse as sp
|
||||
import scipy.sparse.linalg as sla
|
||||
|
||||
from .. import comm
|
||||
|
||||
|
||||
def deplete(chain, x, op_result, dt, print_out):
|
||||
"""Deplete materials using given reaction rates for a specified time
|
||||
|
||||
Parameters
|
||||
----------
|
||||
chain : openmc.deplete.Chain
|
||||
Depletion chain
|
||||
x : list of numpy.ndarray
|
||||
Atom number vectors for each material
|
||||
op_result : openmc.deplete.OperatorResult
|
||||
Result of applying transport operator (contains reaction rates)
|
||||
dt : float
|
||||
Time in [s] to deplete for
|
||||
print_out : bool
|
||||
Whether to show elapsed time
|
||||
|
||||
Returns
|
||||
-------
|
||||
x_result : list of numpy.ndarray
|
||||
Updated atom number vectors for each material
|
||||
|
||||
"""
|
||||
t_start = time.time()
|
||||
|
||||
# Set up iterators
|
||||
n_mats = len(x)
|
||||
chains = repeat(chain, n_mats)
|
||||
vecs = (x[i] for i in range(n_mats))
|
||||
rates = (op_result.rates[i, :, :] for i in range(n_mats))
|
||||
dts = repeat(dt, n_mats)
|
||||
|
||||
# Use multiprocessing pool to distribute work
|
||||
with Pool() as pool:
|
||||
iters = zip(chains, vecs, rates, dts)
|
||||
x_result = list(pool.starmap(_cram_wrapper, iters))
|
||||
|
||||
t_end = time.time()
|
||||
if comm.rank == 0:
|
||||
if print_out:
|
||||
print("Time to matexp: ", t_end - t_start)
|
||||
|
||||
return x_result
|
||||
|
||||
|
||||
def _cram_wrapper(chain, n0, rates, dt):
|
||||
"""Wraps depletion matrix creation / CRAM solve for multiprocess execution
|
||||
|
||||
Parameters
|
||||
----------
|
||||
chain : DepletionChain
|
||||
Depletion chain used to construct the burnup matrix
|
||||
n0 : numpy.array
|
||||
Vector to operate a matrix exponent on.
|
||||
rates : numpy.ndarray
|
||||
2D array indexed by nuclide then by cell.
|
||||
dt : float
|
||||
Time to integrate to.
|
||||
|
||||
Returns
|
||||
-------
|
||||
numpy.array
|
||||
Results of the matrix exponent.
|
||||
"""
|
||||
A = chain.form_matrix(rates)
|
||||
return CRAM48(A, n0, dt)
|
||||
|
||||
|
||||
def CRAM16(A, n0, dt):
|
||||
"""Chebyshev Rational Approximation Method, order 16
|
||||
|
||||
Algorithm is the 16th order Chebyshev Rational Approximation Method,
|
||||
implemented in the more stable `incomplete partial fraction (IPF)
|
||||
<https://doi.org/10.13182/NSE15-26>`_ form.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
A : scipy.linalg.csr_matrix
|
||||
Matrix to take exponent of.
|
||||
n0 : numpy.array
|
||||
Vector to operate a matrix exponent on.
|
||||
dt : float
|
||||
Time to integrate to.
|
||||
|
||||
Returns
|
||||
-------
|
||||
numpy.array
|
||||
Results of the matrix exponent.
|
||||
|
||||
"""
|
||||
|
||||
alpha = np.array([+2.124853710495224e-16,
|
||||
+5.464930576870210e+3 - 3.797983575308356e+4j,
|
||||
+9.045112476907548e+1 - 1.115537522430261e+3j,
|
||||
+2.344818070467641e+2 - 4.228020157070496e+2j,
|
||||
+9.453304067358312e+1 - 2.951294291446048e+2j,
|
||||
+7.283792954673409e+2 - 1.205646080220011e+5j,
|
||||
+3.648229059594851e+1 - 1.155509621409682e+2j,
|
||||
+2.547321630156819e+1 - 2.639500283021502e+1j,
|
||||
+2.394538338734709e+1 - 5.650522971778156e+0j],
|
||||
dtype=np.complex128)
|
||||
theta = np.array([+0.0,
|
||||
+3.509103608414918 + 8.436198985884374j,
|
||||
+5.948152268951177 + 3.587457362018322j,
|
||||
-5.264971343442647 + 16.22022147316793j,
|
||||
+1.419375897185666 + 10.92536348449672j,
|
||||
+6.416177699099435 + 1.194122393370139j,
|
||||
+4.993174737717997 + 5.996881713603942j,
|
||||
-1.413928462488886 + 13.49772569889275j,
|
||||
-10.84391707869699 + 19.27744616718165j],
|
||||
dtype=np.complex128)
|
||||
|
||||
n = A.shape[0]
|
||||
|
||||
alpha0 = 2.124853710495224e-16
|
||||
|
||||
k = 8
|
||||
|
||||
y = np.array(n0, dtype=np.float64)
|
||||
for l in range(1, k+1):
|
||||
y = 2.0*np.real(alpha[l]*sla.spsolve(A*dt - theta[l]*sp.eye(n), y)) + y
|
||||
|
||||
y *= alpha0
|
||||
return y
|
||||
|
||||
|
||||
def CRAM48(A, n0, dt):
|
||||
"""Chebyshev Rational Approximation Method, order 48
|
||||
|
||||
Algorithm is the 48th order Chebyshev Rational Approximation Method,
|
||||
implemented in the more stable `incomplete partial fraction (IPF)
|
||||
<https://doi.org/10.13182/NSE15-26>`_ form.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
A : scipy.linalg.csr_matrix
|
||||
Matrix to take exponent of.
|
||||
n0 : numpy.array
|
||||
Vector to operate a matrix exponent on.
|
||||
dt : float
|
||||
Time to integrate to.
|
||||
|
||||
Returns
|
||||
-------
|
||||
numpy.array
|
||||
Results of the matrix exponent.
|
||||
|
||||
"""
|
||||
|
||||
theta_r = np.array([-4.465731934165702e+1, -5.284616241568964e+0,
|
||||
-8.867715667624458e+0, +3.493013124279215e+0,
|
||||
+1.564102508858634e+1, +1.742097597385893e+1,
|
||||
-2.834466755180654e+1, +1.661569367939544e+1,
|
||||
+8.011836167974721e+0, -2.056267541998229e+0,
|
||||
+1.449208170441839e+1, +1.853807176907916e+1,
|
||||
+9.932562704505182e+0, -2.244223871767187e+1,
|
||||
+8.590014121680897e-1, -1.286192925744479e+1,
|
||||
+1.164596909542055e+1, +1.806076684783089e+1,
|
||||
+5.870672154659249e+0, -3.542938819659747e+1,
|
||||
+1.901323489060250e+1, +1.885508331552577e+1,
|
||||
-1.734689708174982e+1, +1.316284237125190e+1])
|
||||
theta_i = np.array([+6.233225190695437e+1, +4.057499381311059e+1,
|
||||
+4.325515754166724e+1, +3.281615453173585e+1,
|
||||
+1.558061616372237e+1, +1.076629305714420e+1,
|
||||
+5.492841024648724e+1, +1.316994930024688e+1,
|
||||
+2.780232111309410e+1, +3.794824788914354e+1,
|
||||
+1.799988210051809e+1, +5.974332563100539e+0,
|
||||
+2.532823409972962e+1, +5.179633600312162e+1,
|
||||
+3.536456194294350e+1, +4.600304902833652e+1,
|
||||
+2.287153304140217e+1, +8.368200580099821e+0,
|
||||
+3.029700159040121e+1, +5.834381701800013e+1,
|
||||
+1.194282058271408e+0, +3.583428564427879e+0,
|
||||
+4.883941101108207e+1, +2.042951874827759e+1])
|
||||
theta = np.array(theta_r + theta_i * 1j, dtype=np.complex128)
|
||||
|
||||
alpha_r = np.array([+6.387380733878774e+2, +1.909896179065730e+2,
|
||||
+4.236195226571914e+2, +4.645770595258726e+2,
|
||||
+7.765163276752433e+2, +1.907115136768522e+3,
|
||||
+2.909892685603256e+3, +1.944772206620450e+2,
|
||||
+1.382799786972332e+5, +5.628442079602433e+3,
|
||||
+2.151681283794220e+2, +1.324720240514420e+3,
|
||||
+1.617548476343347e+4, +1.112729040439685e+2,
|
||||
+1.074624783191125e+2, +8.835727765158191e+1,
|
||||
+9.354078136054179e+1, +9.418142823531573e+1,
|
||||
+1.040012390717851e+2, +6.861882624343235e+1,
|
||||
+8.766654491283722e+1, +1.056007619389650e+2,
|
||||
+7.738987569039419e+1, +1.041366366475571e+2])
|
||||
alpha_i = np.array([-6.743912502859256e+2, -3.973203432721332e+2,
|
||||
-2.041233768918671e+3, -1.652917287299683e+3,
|
||||
-1.783617639907328e+4, -5.887068595142284e+4,
|
||||
-9.953255345514560e+3, -1.427131226068449e+3,
|
||||
-3.256885197214938e+6, -2.924284515884309e+4,
|
||||
-1.121774011188224e+3, -6.370088443140973e+4,
|
||||
-1.008798413156542e+6, -8.837109731680418e+1,
|
||||
-1.457246116408180e+2, -6.388286188419360e+1,
|
||||
-2.195424319460237e+2, -6.719055740098035e+2,
|
||||
-1.693747595553868e+2, -1.177598523430493e+1,
|
||||
-4.596464999363902e+3, -1.738294585524067e+3,
|
||||
-4.311715386228984e+1, -2.777743732451969e+2])
|
||||
alpha = np.array(alpha_r + alpha_i * 1j, dtype=np.complex128)
|
||||
n = A.shape[0]
|
||||
|
||||
alpha0 = 2.258038182743983e-47
|
||||
|
||||
k = 24
|
||||
|
||||
y = np.array(n0, dtype=np.float64)
|
||||
for l in range(k):
|
||||
y = 2.0*np.real(alpha[l]*sla.spsolve(A*dt - theta[l]*sp.eye(n), y)) + y
|
||||
|
||||
y *= alpha0
|
||||
return y
|
||||
66
openmc/deplete/integrator/predictor.py
Normal file
66
openmc/deplete/integrator/predictor.py
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
"""First-order predictor algorithm."""
|
||||
|
||||
import copy
|
||||
from collections.abc import Iterable
|
||||
|
||||
from .cram import deplete
|
||||
from ..results import Results
|
||||
|
||||
|
||||
def predictor(operator, timesteps, power, print_out=True):
|
||||
r"""Deplete using a first-order predictor algorithm.
|
||||
|
||||
Implements the first-order predictor algorithm. This algorithm is
|
||||
mathematically defined as:
|
||||
|
||||
.. math::
|
||||
y' &= A(y, t) y(t)
|
||||
|
||||
A_p &= A(y_n, t_n)
|
||||
|
||||
y_{n+1} &= \text{expm}(A_p h) y_n
|
||||
|
||||
Parameters
|
||||
----------
|
||||
operator : openmc.deplete.TransportOperator
|
||||
The operator object to simulate on.
|
||||
timesteps : iterable of float
|
||||
Array of timesteps in units of [s]. Note that values are not cumulative.
|
||||
power : float or iterable of float
|
||||
Power of the reactor in [W]. A single value indicates that the power is
|
||||
constant over all timesteps. An iterable indicates potentially different
|
||||
power levels for each timestep. For a 2D problem, the power can be given
|
||||
in [W/cm] as long as the "volume" assigned to a depletion material is
|
||||
actually an area in [cm^2].
|
||||
print_out : bool, optional
|
||||
Whether or not to print out time.
|
||||
|
||||
"""
|
||||
if not isinstance(power, Iterable):
|
||||
power = [power]*len(timesteps)
|
||||
|
||||
# Generate initial conditions
|
||||
with operator as vec:
|
||||
chain = operator.chain
|
||||
t = 0.0
|
||||
for i, (dt, p) in enumerate(zip(timesteps, power)):
|
||||
# Get beginning-of-timestep reaction rates
|
||||
x = [copy.deepcopy(vec)]
|
||||
op_results = [operator(x[0], p)]
|
||||
|
||||
# Create results, write to disk
|
||||
Results.save(operator, x, op_results, [t, t + dt], i)
|
||||
|
||||
# Deplete for full timestep
|
||||
x_end = deplete(chain, x[0], op_results[0], dt, print_out)
|
||||
|
||||
# Advance time, update vector
|
||||
t += dt
|
||||
vec = copy.deepcopy(x_end)
|
||||
|
||||
# Perform one last simulation
|
||||
x = [copy.deepcopy(vec)]
|
||||
op_results = [operator(x[0], power[-1])]
|
||||
|
||||
# Create results, write to disk
|
||||
Results.save(operator, x, op_results, [t, t], len(timesteps))
|
||||
219
openmc/deplete/nuclide.py
Normal file
219
openmc/deplete/nuclide.py
Normal file
|
|
@ -0,0 +1,219 @@
|
|||
"""Nuclide module.
|
||||
|
||||
Contains the per-nuclide components of a depletion chain.
|
||||
"""
|
||||
|
||||
from collections import namedtuple
|
||||
try:
|
||||
import lxml.etree as ET
|
||||
except ImportError:
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
|
||||
DecayTuple = namedtuple('DecayTuple', 'type target branching_ratio')
|
||||
DecayTuple.__doc__ = """\
|
||||
Decay mode information
|
||||
|
||||
Parameters
|
||||
----------
|
||||
type : str
|
||||
Type of the decay mode, e.g., 'beta-'
|
||||
target : str
|
||||
Nuclide resulting from decay
|
||||
branching_ratio : float
|
||||
Branching ratio of the decay mode
|
||||
|
||||
"""
|
||||
try:
|
||||
DecayTuple.type.__doc__ = None
|
||||
DecayTuple.target.__doc__ = None
|
||||
DecayTuple.branching_ratio.__doc__ = None
|
||||
except AttributeError:
|
||||
# Can't set __doc__ on properties on Python 3.4
|
||||
pass
|
||||
|
||||
|
||||
ReactionTuple = namedtuple('ReactionTuple', 'type target Q branching_ratio')
|
||||
ReactionTuple.__doc__ = """\
|
||||
Transmutation reaction information
|
||||
|
||||
Parameters
|
||||
----------
|
||||
type : str
|
||||
Type of the reaction, e.g., 'fission'
|
||||
target : str
|
||||
nuclide resulting from reaction
|
||||
Q : float
|
||||
Q value of the reaction in [eV]
|
||||
branching_ratio : float
|
||||
Branching ratio of the reaction
|
||||
|
||||
"""
|
||||
try:
|
||||
ReactionTuple.type.__doc__ = None
|
||||
ReactionTuple.target.__doc__ = None
|
||||
ReactionTuple.Q.__doc__ = None
|
||||
ReactionTuple.branching_ratio.__doc__ = None
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
|
||||
class Nuclide(object):
|
||||
"""Decay modes, reactions, and fission yields for a single nuclide.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
name : str
|
||||
Name of nuclide.
|
||||
half_life : float
|
||||
Half life of nuclide in [s].
|
||||
decay_energy : float
|
||||
Energy deposited from decay in [eV].
|
||||
n_decay_modes : int
|
||||
Number of decay pathways.
|
||||
decay_modes : list of openmc.deplete.DecayTuple
|
||||
Decay mode information. Each element of the list is a named tuple with
|
||||
attributes 'type', 'target', and 'branching_ratio'.
|
||||
n_reaction_paths : int
|
||||
Number of possible reaction pathways.
|
||||
reactions : list of openmc.deplete.ReactionTuple
|
||||
Reaction information. Each element of the list is a named tuple with
|
||||
attribute 'type', 'target', 'Q', and 'branching_ratio'.
|
||||
yield_data : dict of float to list
|
||||
Maps tabulated energy to list of (product, yield) for all
|
||||
neutron-induced fission products.
|
||||
yield_energies : list of float
|
||||
Energies at which fission product yiels exist
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
# Information about the nuclide
|
||||
self.name = None
|
||||
self.half_life = None
|
||||
self.decay_energy = 0.0
|
||||
|
||||
# Decay paths
|
||||
self.decay_modes = []
|
||||
|
||||
# Reaction paths
|
||||
self.reactions = []
|
||||
|
||||
# Neutron fission yields, if present
|
||||
self.yield_data = {}
|
||||
self.yield_energies = []
|
||||
|
||||
@property
|
||||
def n_decay_modes(self):
|
||||
return len(self.decay_modes)
|
||||
|
||||
@property
|
||||
def n_reaction_paths(self):
|
||||
return len(self.reactions)
|
||||
|
||||
@classmethod
|
||||
def from_xml(cls, element):
|
||||
"""Read nuclide from an XML element.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
element : xml.etree.ElementTree.Element
|
||||
XML element to write nuclide data to
|
||||
|
||||
Returns
|
||||
-------
|
||||
nuc : openmc.deplete.Nuclide
|
||||
Instance of a nuclide
|
||||
|
||||
"""
|
||||
nuc = cls()
|
||||
nuc.name = element.get('name')
|
||||
|
||||
# Check for half-life
|
||||
if 'half_life' in element.attrib:
|
||||
nuc.half_life = float(element.get('half_life'))
|
||||
nuc.decay_energy = float(element.get('decay_energy', '0'))
|
||||
|
||||
# Check for decay paths
|
||||
for decay_elem in element.iter('decay'):
|
||||
d_type = decay_elem.get('type')
|
||||
target = decay_elem.get('target')
|
||||
branching_ratio = float(decay_elem.get('branching_ratio'))
|
||||
nuc.decay_modes.append(DecayTuple(d_type, target, branching_ratio))
|
||||
|
||||
# Check for reaction paths
|
||||
for reaction_elem in element.iter('reaction'):
|
||||
r_type = reaction_elem.get('type')
|
||||
Q = float(reaction_elem.get('Q', '0'))
|
||||
branching_ratio = float(reaction_elem.get('branching_ratio', '1'))
|
||||
|
||||
# If the type is not fission, get target and Q value, otherwise
|
||||
# just set null values
|
||||
if r_type != 'fission':
|
||||
target = reaction_elem.get('target')
|
||||
else:
|
||||
target = None
|
||||
|
||||
# Append reaction
|
||||
nuc.reactions.append(ReactionTuple(
|
||||
r_type, target, Q, branching_ratio))
|
||||
|
||||
fpy_elem = element.find('neutron_fission_yields')
|
||||
if fpy_elem is not None:
|
||||
for yields_elem in fpy_elem.iter('fission_yields'):
|
||||
E = float(yields_elem.get('energy'))
|
||||
products = yields_elem.find('products').text.split()
|
||||
yields = [float(y) for y in
|
||||
yields_elem.find('data').text.split()]
|
||||
nuc.yield_data[E] = list(zip(products, yields))
|
||||
nuc.yield_energies = list(sorted(nuc.yield_data.keys()))
|
||||
|
||||
return nuc
|
||||
|
||||
def to_xml_element(self):
|
||||
"""Write nuclide to XML element.
|
||||
|
||||
Returns
|
||||
-------
|
||||
elem : xml.etree.ElementTree.Element
|
||||
XML element to write nuclide data to
|
||||
|
||||
"""
|
||||
elem = ET.Element('nuclide')
|
||||
elem.set('name', self.name)
|
||||
|
||||
if self.half_life is not None:
|
||||
elem.set('half_life', str(self.half_life))
|
||||
elem.set('decay_modes', str(len(self.decay_modes)))
|
||||
elem.set('decay_energy', str(self.decay_energy))
|
||||
for mode, daughter, br in self.decay_modes:
|
||||
mode_elem = ET.SubElement(elem, 'decay')
|
||||
mode_elem.set('type', mode)
|
||||
mode_elem.set('target', daughter)
|
||||
mode_elem.set('branching_ratio', str(br))
|
||||
|
||||
elem.set('reactions', str(len(self.reactions)))
|
||||
for rx, daughter, Q, br in self.reactions:
|
||||
rx_elem = ET.SubElement(elem, 'reaction')
|
||||
rx_elem.set('type', rx)
|
||||
rx_elem.set('Q', str(Q))
|
||||
if rx != 'fission':
|
||||
rx_elem.set('target', daughter)
|
||||
if br != 1.0:
|
||||
rx_elem.set('branching_ratio', str(br))
|
||||
|
||||
if self.yield_data:
|
||||
fpy_elem = ET.SubElement(elem, 'neutron_fission_yields')
|
||||
energy_elem = ET.SubElement(fpy_elem, 'energies')
|
||||
energy_elem.text = ' '.join(str(E) for E in self.yield_energies)
|
||||
|
||||
for E in self.yield_energies:
|
||||
yields_elem = ET.SubElement(fpy_elem, 'fission_yields')
|
||||
yields_elem.set('energy', str(E))
|
||||
|
||||
products_elem = ET.SubElement(yields_elem, 'products')
|
||||
products_elem.text = ' '.join(x[0] for x in self.yield_data[E])
|
||||
data_elem = ET.SubElement(yields_elem, 'data')
|
||||
data_elem.text = ' '.join(str(x[1]) for x in self.yield_data[E])
|
||||
|
||||
return elem
|
||||
562
openmc/deplete/operator.py
Normal file
562
openmc/deplete/operator.py
Normal file
|
|
@ -0,0 +1,562 @@
|
|||
"""OpenMC transport operator
|
||||
|
||||
This module implements a transport operator for OpenMC so that it can be used by
|
||||
depletion integrators. The implementation makes use of the Python bindings to
|
||||
OpenMC's C API so that reading tally results and updating material number
|
||||
densities is all done in-memory instead of through the filesystem.
|
||||
|
||||
"""
|
||||
|
||||
import copy
|
||||
from collections import OrderedDict
|
||||
from itertools import chain
|
||||
import os
|
||||
import time
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
import h5py
|
||||
import numpy as np
|
||||
|
||||
import openmc
|
||||
import openmc.capi
|
||||
from openmc.data import JOULE_PER_EV
|
||||
from . import comm
|
||||
from .abc import TransportOperator, OperatorResult
|
||||
from .atom_number import AtomNumber
|
||||
from .reaction_rates import ReactionRates
|
||||
|
||||
|
||||
def _distribute(items):
|
||||
"""Distribute items across MPI communicator
|
||||
|
||||
Parameters
|
||||
----------
|
||||
items : list
|
||||
List of items of distribute
|
||||
|
||||
Returns
|
||||
-------
|
||||
list
|
||||
Items assigned to process that called
|
||||
|
||||
"""
|
||||
min_size, extra = divmod(len(items), comm.size)
|
||||
j = 0
|
||||
for i in range(comm.size):
|
||||
chunk_size = min_size + int(i < extra)
|
||||
if comm.rank == i:
|
||||
return items[j:j + chunk_size]
|
||||
j += chunk_size
|
||||
|
||||
|
||||
class Operator(TransportOperator):
|
||||
"""OpenMC transport operator for depletion.
|
||||
|
||||
Instances of this class can be used to perform depletion using OpenMC as the
|
||||
transport operator. Normally, a user needn't call methods of this class
|
||||
directly. Instead, an instance of this class is passed to an integrator
|
||||
function, such as :func:`openmc.deplete.integrator.cecm`.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
geometry : openmc.Geometry
|
||||
OpenMC geometry object
|
||||
settings : openmc.Settings
|
||||
OpenMC Settings object
|
||||
chain_file : str, optional
|
||||
Path to the depletion chain XML file. Defaults to the
|
||||
:envvar:`OPENMC_DEPLETE_CHAIN` environment variable if it exists.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
geometry : openmc.Geometry
|
||||
OpenMC geometry object
|
||||
settings : openmc.Settings
|
||||
OpenMC settings object
|
||||
dilute_initial : float
|
||||
Initial atom density to add for nuclides that are zero in initial
|
||||
condition to ensure they exist in the decay chain. Only done for
|
||||
nuclides with reaction rates. Defaults to 1.0e3.
|
||||
output_dir : pathlib.Path
|
||||
Path to output directory to save results.
|
||||
round_number : bool
|
||||
Whether or not to round output to OpenMC to 8 digits.
|
||||
Useful in testing, as OpenMC is incredibly sensitive to exact values.
|
||||
number : openmc.deplete.AtomNumber
|
||||
Total number of atoms in simulation.
|
||||
nuclides_with_data : set of str
|
||||
A set listing all unique nuclides available from cross_sections.xml.
|
||||
chain : openmc.deplete.Chain
|
||||
The depletion chain information necessary to form matrices and tallies.
|
||||
reaction_rates : openmc.deplete.ReactionRates
|
||||
Reaction rates from the last operator step.
|
||||
burnable_mats : list of str
|
||||
All burnable material IDs
|
||||
local_mats : list of str
|
||||
All burnable material IDs being managed by a single process
|
||||
|
||||
"""
|
||||
def __init__(self, geometry, settings, chain_file=None):
|
||||
super().__init__(chain_file)
|
||||
self.round_number = False
|
||||
self.settings = settings
|
||||
self.geometry = geometry
|
||||
|
||||
# Clear out OpenMC, create task lists, distribute
|
||||
openmc.reset_auto_ids()
|
||||
self.burnable_mats, volume, nuclides = self._get_burnable_mats()
|
||||
self.local_mats = _distribute(self.burnable_mats)
|
||||
|
||||
# Determine which nuclides have incident neutron data
|
||||
self.nuclides_with_data = self._get_nuclides_with_data()
|
||||
self._burnable_nucs = [nuc for nuc in self.nuclides_with_data
|
||||
if nuc in self.chain]
|
||||
|
||||
# Extract number densities from the geometry
|
||||
self._extract_number(self.local_mats, volume, nuclides)
|
||||
|
||||
# Create reaction rates array
|
||||
self.reaction_rates = ReactionRates(
|
||||
self.local_mats, self._burnable_nucs, self.chain.reactions)
|
||||
|
||||
def __call__(self, vec, power, print_out=True):
|
||||
"""Runs a simulation.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
vec : list of numpy.ndarray
|
||||
Total atoms to be used in function.
|
||||
power : float
|
||||
Power of the reactor in [W]
|
||||
print_out : bool, optional
|
||||
Whether or not to print out time.
|
||||
|
||||
Returns
|
||||
-------
|
||||
openmc.deplete.OperatorResult
|
||||
Eigenvalue and reaction rates resulting from transport operator
|
||||
|
||||
"""
|
||||
# Prevent OpenMC from complaining about re-creating tallies
|
||||
openmc.reset_auto_ids()
|
||||
|
||||
# Update status
|
||||
self.number.set_density(vec)
|
||||
|
||||
time_start = time.time()
|
||||
|
||||
# Update material compositions and tally nuclides
|
||||
self._update_materials()
|
||||
self._tally.nuclides = self._get_tally_nuclides()
|
||||
|
||||
# Run OpenMC
|
||||
openmc.capi.reset()
|
||||
openmc.capi.run()
|
||||
|
||||
time_openmc = time.time()
|
||||
|
||||
# Extract results
|
||||
op_result = self._unpack_tallies_and_normalize(power)
|
||||
|
||||
if comm.rank == 0:
|
||||
time_unpack = time.time()
|
||||
|
||||
if print_out:
|
||||
print("Time to openmc: ", time_openmc - time_start)
|
||||
print("Time to unpack: ", time_unpack - time_openmc)
|
||||
|
||||
return copy.deepcopy(op_result)
|
||||
|
||||
def _get_burnable_mats(self):
|
||||
"""Determine depletable materials, volumes, and nuclids
|
||||
|
||||
Returns
|
||||
-------
|
||||
burnable_mats : list of str
|
||||
List of burnable material IDs
|
||||
volume : OrderedDict of str to float
|
||||
Volume of each material in [cm^3]
|
||||
nuclides : list of str
|
||||
Nuclides in order of how they'll appear in the simulation.
|
||||
|
||||
"""
|
||||
burnable_mats = set()
|
||||
model_nuclides = set()
|
||||
volume = OrderedDict()
|
||||
|
||||
# Iterate once through the geometry to get dictionaries
|
||||
for mat in self.geometry.get_all_materials().values():
|
||||
for nuclide in mat.get_nuclides():
|
||||
model_nuclides.add(nuclide)
|
||||
if mat.depletable:
|
||||
burnable_mats.add(str(mat.id))
|
||||
if mat.volume is None:
|
||||
raise RuntimeError("Volume not specified for depletable "
|
||||
"material with ID={}.".format(mat.id))
|
||||
volume[str(mat.id)] = mat.volume
|
||||
|
||||
# Make sure there are burnable materials
|
||||
if not burnable_mats:
|
||||
raise RuntimeError(
|
||||
"No depletable materials were found in the model.")
|
||||
|
||||
# Sort the sets
|
||||
burnable_mats = sorted(burnable_mats, key=int)
|
||||
model_nuclides = sorted(model_nuclides)
|
||||
|
||||
# Construct a global nuclide dictionary, burned first
|
||||
nuclides = list(self.chain.nuclide_dict)
|
||||
for nuc in model_nuclides:
|
||||
if nuc not in nuclides:
|
||||
nuclides.append(nuc)
|
||||
|
||||
return burnable_mats, volume, nuclides
|
||||
|
||||
def _extract_number(self, local_mats, volume, nuclides):
|
||||
"""Construct AtomNumber using geometry
|
||||
|
||||
Parameters
|
||||
----------
|
||||
local_mats : list of str
|
||||
Material IDs to be managed by this process
|
||||
volume : OrderedDict of str to float
|
||||
Volumes for the above materials in [cm^3]
|
||||
nuclides : list of str
|
||||
Nuclides to be used in the simulation.
|
||||
|
||||
"""
|
||||
self.number = AtomNumber(local_mats, nuclides, volume, len(self.chain))
|
||||
|
||||
if self.dilute_initial != 0.0:
|
||||
for nuc in self._burnable_nucs:
|
||||
self.number.set_atom_density(np.s_[:], nuc, self.dilute_initial)
|
||||
|
||||
# Now extract the number densities and store
|
||||
for mat in self.geometry.get_all_materials().values():
|
||||
if str(mat.id) in local_mats:
|
||||
self._set_number_from_mat(mat)
|
||||
|
||||
def _set_number_from_mat(self, mat):
|
||||
"""Extracts material and number densities from openmc.Material
|
||||
|
||||
Parameters
|
||||
----------
|
||||
mat : openmc.Material
|
||||
The material to read from
|
||||
|
||||
"""
|
||||
mat_id = str(mat.id)
|
||||
|
||||
for nuclide, density in mat.get_nuclide_atom_densities().values():
|
||||
number = density * 1.0e24
|
||||
self.number.set_atom_density(mat_id, nuclide, number)
|
||||
|
||||
def initial_condition(self):
|
||||
"""Performs final setup and returns initial condition.
|
||||
|
||||
Returns
|
||||
-------
|
||||
list of numpy.ndarray
|
||||
Total density for initial conditions.
|
||||
"""
|
||||
|
||||
# Create XML files
|
||||
if comm.rank == 0:
|
||||
self.geometry.export_to_xml()
|
||||
self.settings.export_to_xml()
|
||||
self._generate_materials_xml()
|
||||
|
||||
# Initialize OpenMC library
|
||||
comm.barrier()
|
||||
openmc.capi.init(comm)
|
||||
|
||||
# Generate tallies in memory
|
||||
self._generate_tallies()
|
||||
|
||||
# Return number density vector
|
||||
return list(self.number.get_mat_slice(np.s_[:]))
|
||||
|
||||
def finalize(self):
|
||||
"""Finalize a depletion simulation and release resources."""
|
||||
openmc.capi.finalize()
|
||||
|
||||
def _update_materials(self):
|
||||
"""Updates material compositions in OpenMC on all processes."""
|
||||
|
||||
for rank in range(comm.size):
|
||||
number_i = comm.bcast(self.number, root=rank)
|
||||
|
||||
for mat in number_i.materials:
|
||||
nuclides = []
|
||||
densities = []
|
||||
for nuc in number_i.nuclides:
|
||||
if nuc in self.nuclides_with_data:
|
||||
val = 1.0e-24 * number_i.get_atom_density(mat, nuc)
|
||||
|
||||
# If nuclide is zero, do not add to the problem.
|
||||
if val > 0.0:
|
||||
if self.round_number:
|
||||
val_magnitude = np.floor(np.log10(val))
|
||||
val_scaled = val / 10**val_magnitude
|
||||
val_round = round(val_scaled, 8)
|
||||
|
||||
val = val_round * 10**val_magnitude
|
||||
|
||||
nuclides.append(nuc)
|
||||
densities.append(val)
|
||||
else:
|
||||
# Only output warnings if values are significantly
|
||||
# negative. CRAM does not guarantee positive values.
|
||||
if val < -1.0e-21:
|
||||
print("WARNING: nuclide ", nuc, " in material ", mat,
|
||||
" is negative (density = ", val, " at/barn-cm)")
|
||||
number_i[mat, nuc] = 0.0
|
||||
|
||||
mat_internal = openmc.capi.materials[int(mat)]
|
||||
mat_internal.set_densities(nuclides, densities)
|
||||
|
||||
def _generate_materials_xml(self):
|
||||
"""Creates materials.xml from self.number.
|
||||
|
||||
Due to uncertainty with how MPI interacts with OpenMC API, this
|
||||
constructs the XML manually. The long term goal is to do this
|
||||
through direct memory writing.
|
||||
|
||||
"""
|
||||
materials = openmc.Materials(self.geometry.get_all_materials()
|
||||
.values())
|
||||
|
||||
# Sort nuclides according to order in AtomNumber object
|
||||
nuclides = list(self.number.nuclides)
|
||||
for mat in materials:
|
||||
mat._nuclides.sort(key=lambda x: nuclides.index(x[0]))
|
||||
|
||||
materials.export_to_xml()
|
||||
|
||||
def _get_tally_nuclides(self):
|
||||
"""Determine nuclides that should be tallied for reaction rates.
|
||||
|
||||
This method returns a list of all nuclides that have neutron data and
|
||||
are listed in the depletion chain. Technically, we should tally nuclides
|
||||
that may not appear in the depletion chain because we still need to get
|
||||
the fission reaction rate for these nuclides in order to normalize
|
||||
power, but that is left as a future exercise.
|
||||
|
||||
Returns
|
||||
-------
|
||||
list of str
|
||||
Tally nuclides
|
||||
|
||||
"""
|
||||
nuc_set = set()
|
||||
|
||||
# Create the set of all nuclides in the decay chain in materials marked
|
||||
# for burning in which the number density is greater than zero.
|
||||
for nuc in self.number.nuclides:
|
||||
if nuc in self.nuclides_with_data:
|
||||
if np.sum(self.number[:, nuc]) > 0.0:
|
||||
nuc_set.add(nuc)
|
||||
|
||||
# Communicate which nuclides have nonzeros to rank 0
|
||||
if comm.rank == 0:
|
||||
for i in range(1, comm.size):
|
||||
nuc_newset = comm.recv(source=i, tag=i)
|
||||
nuc_set |= nuc_newset
|
||||
else:
|
||||
comm.send(nuc_set, dest=0, tag=comm.rank)
|
||||
|
||||
if comm.rank == 0:
|
||||
# Sort nuclides in the same order as self.number
|
||||
nuc_list = [nuc for nuc in self.number.nuclides
|
||||
if nuc in nuc_set]
|
||||
else:
|
||||
nuc_list = None
|
||||
|
||||
# Store list of tally nuclides on each process
|
||||
nuc_list = comm.bcast(nuc_list)
|
||||
return [nuc for nuc in nuc_list if nuc in self.chain]
|
||||
|
||||
def _generate_tallies(self):
|
||||
"""Generates depletion tallies.
|
||||
|
||||
Using information from the depletion chain as well as the nuclides
|
||||
currently in the problem, this function automatically generates a
|
||||
tally.xml for the simulation.
|
||||
|
||||
"""
|
||||
# Create tallies for depleting regions
|
||||
materials = [openmc.capi.materials[int(i)]
|
||||
for i in self.burnable_mats]
|
||||
mat_filter = openmc.capi.MaterialFilter(materials)
|
||||
|
||||
# Set up a tally that has a material filter covering each depletable
|
||||
# material and scores corresponding to all reactions that cause
|
||||
# transmutation. The nuclides for the tally are set later when eval() is
|
||||
# called.
|
||||
self._tally = openmc.capi.Tally()
|
||||
self._tally.scores = self.chain.reactions
|
||||
self._tally.filters = [mat_filter]
|
||||
|
||||
def _unpack_tallies_and_normalize(self, power):
|
||||
"""Unpack tallies from OpenMC and return an operator result
|
||||
|
||||
This method uses OpenMC's C API bindings to determine the k-effective
|
||||
value and reaction rates from the simulation. The reaction rates are
|
||||
normalized by the user-specified power, summing the product of the
|
||||
fission reaction rate times the fission Q value for each material.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
power : float
|
||||
Power of the reactor in [W]
|
||||
|
||||
Returns
|
||||
-------
|
||||
openmc.deplete.OperatorResult
|
||||
Eigenvalue and reaction rates resulting from transport operator
|
||||
|
||||
"""
|
||||
rates = self.reaction_rates
|
||||
rates[:, :, :] = 0.0
|
||||
|
||||
k_combined = openmc.capi.keff()[0]
|
||||
|
||||
# Extract tally bins
|
||||
materials = self.burnable_mats
|
||||
nuclides = self._tally.nuclides
|
||||
|
||||
# Form fast map
|
||||
nuc_ind = [rates.index_nuc[nuc] for nuc in nuclides]
|
||||
react_ind = [rates.index_rx[react] for react in self.chain.reactions]
|
||||
|
||||
# Compute fission power
|
||||
# TODO : improve this calculation
|
||||
|
||||
# Keep track of energy produced from all reactions in eV per source
|
||||
# particle
|
||||
energy = 0.0
|
||||
|
||||
# Create arrays to store fission Q values, reaction rates, and nuclide
|
||||
# numbers
|
||||
fission_Q = np.zeros(rates.n_nuc)
|
||||
rates_expanded = np.zeros((rates.n_nuc, rates.n_react))
|
||||
number = np.zeros(rates.n_nuc)
|
||||
|
||||
fission_ind = rates.index_rx["fission"]
|
||||
|
||||
for nuclide in self.chain.nuclides:
|
||||
if nuclide.name in rates.index_nuc:
|
||||
for rx in nuclide.reactions:
|
||||
if rx.type == 'fission':
|
||||
ind = rates.index_nuc[nuclide.name]
|
||||
fission_Q[ind] = rx.Q
|
||||
break
|
||||
|
||||
# Extract results
|
||||
for i, mat in enumerate(self.local_mats):
|
||||
# Get tally index
|
||||
slab = materials.index(mat)
|
||||
|
||||
# Get material results hyperslab
|
||||
results = self._tally.results[slab, :, 1]
|
||||
|
||||
# Zero out reaction rates and nuclide numbers
|
||||
rates_expanded[:] = 0.0
|
||||
number[:] = 0.0
|
||||
|
||||
# Expand into our memory layout
|
||||
j = 0
|
||||
for nuc, i_nuc_results in zip(nuclides, nuc_ind):
|
||||
number[i_nuc_results] = self.number[mat, nuc]
|
||||
for react in react_ind:
|
||||
rates_expanded[i_nuc_results, react] = results[j]
|
||||
j += 1
|
||||
|
||||
# Accumulate energy from fission
|
||||
energy += np.dot(rates_expanded[:, fission_ind], fission_Q)
|
||||
|
||||
# Divide by total number and store
|
||||
for i_nuc_results in nuc_ind:
|
||||
if number[i_nuc_results] != 0.0:
|
||||
for react in react_ind:
|
||||
rates_expanded[i_nuc_results, react] /= number[i_nuc_results]
|
||||
|
||||
rates[i, :, :] = rates_expanded
|
||||
|
||||
# Reduce energy produced from all processes
|
||||
energy = comm.allreduce(energy)
|
||||
|
||||
# Determine power in eV/s
|
||||
power /= JOULE_PER_EV
|
||||
|
||||
# Scale reaction rates to obtain units of reactions/sec
|
||||
rates *= power / energy
|
||||
|
||||
return OperatorResult(k_combined, rates)
|
||||
|
||||
def _get_nuclides_with_data(self):
|
||||
"""Loads a cross_sections.xml file to find participating nuclides.
|
||||
|
||||
This allows for nuclides that are important in the decay chain but not
|
||||
important neutronically, or have no cross section data.
|
||||
"""
|
||||
|
||||
# Reads cross_sections.xml to create a dictionary containing
|
||||
# participating (burning and not just decaying) nuclides.
|
||||
|
||||
try:
|
||||
filename = os.environ["OPENMC_CROSS_SECTIONS"]
|
||||
except KeyError:
|
||||
filename = None
|
||||
|
||||
nuclides = set()
|
||||
|
||||
try:
|
||||
tree = ET.parse(filename)
|
||||
except Exception:
|
||||
if filename is None:
|
||||
msg = "No cross_sections.xml specified in materials."
|
||||
else:
|
||||
msg = 'Cross section file "{}" is invalid.'.format(filename)
|
||||
raise IOError(msg)
|
||||
|
||||
root = tree.getroot()
|
||||
for nuclide_node in root.findall('library'):
|
||||
mats = nuclide_node.get('materials')
|
||||
if not mats:
|
||||
continue
|
||||
for name in mats.split():
|
||||
# Make a burn list of the union of nuclides in cross_sections.xml
|
||||
# and nuclides in depletion chain.
|
||||
if name not in nuclides:
|
||||
nuclides.add(name)
|
||||
|
||||
return nuclides
|
||||
|
||||
def get_results_info(self):
|
||||
"""Returns volume list, material lists, and nuc lists.
|
||||
|
||||
Returns
|
||||
-------
|
||||
volume : dict of str float
|
||||
Volumes corresponding to materials in full_burn_dict
|
||||
nuc_list : list of str
|
||||
A list of all nuclide names. Used for sorting the simulation.
|
||||
burn_list : list of int
|
||||
A list of all material IDs to be burned. Used for sorting the simulation.
|
||||
full_burn_list : list
|
||||
List of all burnable material IDs
|
||||
|
||||
"""
|
||||
nuc_list = self.number.burnable_nuclides
|
||||
burn_list = self.local_mats
|
||||
|
||||
volume = {}
|
||||
for i, mat in enumerate(burn_list):
|
||||
volume[mat] = self.number.volume[i]
|
||||
|
||||
# Combine volume dictionaries across processes
|
||||
volume_list = comm.allgather(volume)
|
||||
volume = {k: v for d in volume_list for k, v in d.items()}
|
||||
|
||||
return volume, nuc_list, burn_list, self.burnable_mats
|
||||
139
openmc/deplete/reaction_rates.py
Normal file
139
openmc/deplete/reaction_rates.py
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
"""ReactionRates module.
|
||||
|
||||
An ndarray to store reaction rates with string, integer, or slice indexing.
|
||||
"""
|
||||
from collections import OrderedDict
|
||||
|
||||
import numpy as np
|
||||
|
||||
|
||||
class ReactionRates(np.ndarray):
|
||||
"""Reaction rates resulting from a transport operator call
|
||||
|
||||
This class is a subclass of :class:`numpy.ndarray` with a few custom
|
||||
attributes that make it easy to determine what index corresponds to a given
|
||||
material, nuclide, and reaction rate.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
local_mats : list of str
|
||||
Material IDs
|
||||
nuclides : list of str
|
||||
Depletable nuclides
|
||||
reactions : list of str
|
||||
Transmutation reactions being tracked
|
||||
|
||||
Attributes
|
||||
----------
|
||||
index_mat : OrderedDict of str to int
|
||||
A dictionary mapping material ID as string to index.
|
||||
index_nuc : OrderedDict of str to int
|
||||
A dictionary mapping nuclide name as string to index.
|
||||
index_rx : OrderedDict of str to int
|
||||
A dictionary mapping reaction name as string to index.
|
||||
n_mat : int
|
||||
Number of materials.
|
||||
n_nuc : int
|
||||
Number of nucs.
|
||||
n_react : int
|
||||
Number of reactions.
|
||||
|
||||
"""
|
||||
|
||||
# NumPy arrays can be created 1) explicitly 2) using view casting, and 3) by
|
||||
# slicing an existing array. Because of these possibilities, it's necessary
|
||||
# to put initialization logic in __new__ rather than __init__. Additionally,
|
||||
# subclasses need to handle the multiple ways of creating arrays by using
|
||||
# the __array_finalize__ method (discussed here:
|
||||
# https://docs.scipy.org/doc/numpy/user/basics.subclassing.html)
|
||||
|
||||
def __new__(cls, local_mats, nuclides, reactions):
|
||||
# Create appropriately-sized zeroed-out ndarray
|
||||
shape = (len(local_mats), len(nuclides), len(reactions))
|
||||
obj = super().__new__(cls, shape)
|
||||
obj[:] = 0.0
|
||||
|
||||
# Add mapping attributes
|
||||
obj.index_mat = {mat: i for i, mat in enumerate(local_mats)}
|
||||
obj.index_nuc = {nuc: i for i, nuc in enumerate(nuclides)}
|
||||
obj.index_rx = {rx: i for i, rx in enumerate(reactions)}
|
||||
|
||||
return obj
|
||||
|
||||
def __array_finalize__(self, obj):
|
||||
if obj is None:
|
||||
return
|
||||
self.index_mat = getattr(obj, 'index_mat', None)
|
||||
self.index_nuc = getattr(obj, 'index_nuc', None)
|
||||
self.index_rx = getattr(obj, 'index_rx', None)
|
||||
|
||||
# Reaction rates are distributed to other processes via multiprocessing,
|
||||
# which entails pickling the objects. In order to preserve the custom
|
||||
# attributes, we have to modify how the ndarray is pickled as described
|
||||
# here: https://stackoverflow.com/a/26599346/1572453
|
||||
|
||||
def __reduce__(self):
|
||||
state = super().__reduce__()
|
||||
new_state = state[2] + (self.index_mat, self.index_nuc, self.index_rx)
|
||||
return (state[0], state[1], new_state)
|
||||
|
||||
def __setstate__(self, state):
|
||||
self.index_mat = state[-3]
|
||||
self.index_nuc = state[-2]
|
||||
self.index_rx = state[-1]
|
||||
super().__setstate__(state[0:-3])
|
||||
|
||||
@property
|
||||
def n_mat(self):
|
||||
return len(self.index_mat)
|
||||
|
||||
@property
|
||||
def n_nuc(self):
|
||||
return len(self.index_nuc)
|
||||
|
||||
@property
|
||||
def n_react(self):
|
||||
return len(self.index_rx)
|
||||
|
||||
def get(self, mat, nuc, rx):
|
||||
"""Get reaction rate by material/nuclide/reaction
|
||||
|
||||
Parameters
|
||||
----------
|
||||
mat : str
|
||||
Material ID as a string
|
||||
nuc : str
|
||||
Nuclide name
|
||||
rx : str
|
||||
Name of the reaction
|
||||
|
||||
Returns
|
||||
-------
|
||||
float
|
||||
Reaction rate corresponding to given material, nuclide, and reaction
|
||||
|
||||
"""
|
||||
mat = self.index_mat[mat]
|
||||
nuc = self.index_nuc[nuc]
|
||||
rx = self.index_rx[rx]
|
||||
return self[mat, nuc, rx]
|
||||
|
||||
def set(self, mat, nuc, rx, value):
|
||||
"""Set reaction rate by material/nuclide/reaction
|
||||
|
||||
Parameters
|
||||
----------
|
||||
mat : str
|
||||
Material ID as a string
|
||||
nuc : str
|
||||
Nuclide name
|
||||
rx : str
|
||||
Name of the reaction
|
||||
value : float
|
||||
Corresponding reaction rate to set
|
||||
|
||||
"""
|
||||
mat = self.index_mat[mat]
|
||||
nuc = self.index_nuc[nuc]
|
||||
rx = self.index_rx[rx]
|
||||
self[mat, nuc, rx] = value
|
||||
397
openmc/deplete/results.py
Normal file
397
openmc/deplete/results.py
Normal file
|
|
@ -0,0 +1,397 @@
|
|||
"""The results module.
|
||||
|
||||
Contains results generation and saving capabilities.
|
||||
"""
|
||||
|
||||
from collections import OrderedDict
|
||||
import copy
|
||||
|
||||
import numpy as np
|
||||
import h5py
|
||||
|
||||
from . import comm, have_mpi
|
||||
from .reaction_rates import ReactionRates
|
||||
|
||||
_VERSION_RESULTS = (1, 0)
|
||||
|
||||
|
||||
class Results(object):
|
||||
"""Output of a depletion run
|
||||
|
||||
Attributes
|
||||
----------
|
||||
k : list of float
|
||||
Eigenvalue for each substep.
|
||||
time : list of float
|
||||
Time at beginning, end of step, in seconds.
|
||||
n_mat : int
|
||||
Number of mats.
|
||||
n_nuc : int
|
||||
Number of nuclides.
|
||||
rates : list of ReactionRates
|
||||
The reaction rates for each substep.
|
||||
volume : OrderedDict of int to float
|
||||
Dictionary mapping mat id to volume.
|
||||
mat_to_ind : OrderedDict of str to int
|
||||
A dictionary mapping mat ID as string to index.
|
||||
nuc_to_ind : OrderedDict of str to int
|
||||
A dictionary mapping nuclide name as string to index.
|
||||
mat_to_hdf5_ind : OrderedDict of str to int
|
||||
A dictionary mapping mat ID as string to global index.
|
||||
n_hdf5_mats : int
|
||||
Number of materials in entire geometry.
|
||||
n_stages : int
|
||||
Number of stages in simulation.
|
||||
data : numpy.ndarray
|
||||
Atom quantity, stored by stage, mat, then by nuclide.
|
||||
|
||||
"""
|
||||
def __init__(self):
|
||||
self.k = None
|
||||
self.time = None
|
||||
self.rates = None
|
||||
self.volume = None
|
||||
|
||||
self.mat_to_ind = None
|
||||
self.nuc_to_ind = None
|
||||
self.mat_to_hdf5_ind = None
|
||||
|
||||
self.data = None
|
||||
|
||||
def __getitem__(self, pos):
|
||||
"""Retrieves an item from results.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
pos : tuple
|
||||
A three-length tuple containing a stage index, mat index and a nuc
|
||||
index. All can be integers or slices. The second two can be
|
||||
strings corresponding to their respective dictionary.
|
||||
|
||||
Returns
|
||||
-------
|
||||
float
|
||||
The atoms for stage, mat, nuc
|
||||
|
||||
"""
|
||||
stage, mat, nuc = pos
|
||||
if isinstance(mat, str):
|
||||
mat = self.mat_to_ind[mat]
|
||||
if isinstance(nuc, str):
|
||||
nuc = self.nuc_to_ind[nuc]
|
||||
|
||||
return self.data[stage, mat, nuc]
|
||||
|
||||
def __setitem__(self, pos, val):
|
||||
"""Sets an item from results.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
pos : tuple
|
||||
A three-length tuple containing a stage index, mat index and a nuc
|
||||
index. All can be integers or slices. The second two can be
|
||||
strings corresponding to their respective dictionary.
|
||||
|
||||
val : float
|
||||
The value to set data to.
|
||||
|
||||
"""
|
||||
stage, mat, nuc = pos
|
||||
if isinstance(mat, str):
|
||||
mat = self.mat_to_ind[mat]
|
||||
if isinstance(nuc, str):
|
||||
nuc = self.nuc_to_ind[nuc]
|
||||
|
||||
self.data[stage, mat, nuc] = val
|
||||
|
||||
@property
|
||||
def n_mat(self):
|
||||
return len(self.mat_to_ind)
|
||||
|
||||
@property
|
||||
def n_nuc(self):
|
||||
return len(self.nuc_to_ind)
|
||||
|
||||
@property
|
||||
def n_hdf5_mats(self):
|
||||
return len(self.mat_to_hdf5_ind)
|
||||
|
||||
@property
|
||||
def n_stages(self):
|
||||
return self.data.shape[0]
|
||||
|
||||
def allocate(self, volume, nuc_list, burn_list, full_burn_list, stages):
|
||||
"""Allocates memory of Results.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
volume : dict of str float
|
||||
Volumes corresponding to materials in full_burn_dict
|
||||
nuc_list : list of str
|
||||
A list of all nuclide names. Used for sorting the simulation.
|
||||
burn_list : list of int
|
||||
A list of all mat IDs to be burned. Used for sorting the simulation.
|
||||
full_burn_list : list of str
|
||||
List of all burnable material IDs
|
||||
stages : int
|
||||
Number of stages in simulation.
|
||||
|
||||
"""
|
||||
self.volume = copy.deepcopy(volume)
|
||||
self.nuc_to_ind = {nuc: i for i, nuc in enumerate(nuc_list)}
|
||||
self.mat_to_ind = {mat: i for i, mat in enumerate(burn_list)}
|
||||
self.mat_to_hdf5_ind = {mat: i for i, mat in enumerate(full_burn_list)}
|
||||
|
||||
# Create storage array
|
||||
self.data = np.zeros((stages, self.n_mat, self.n_nuc))
|
||||
|
||||
def export_to_hdf5(self, filename, step):
|
||||
"""Export results to an HDF5 file
|
||||
|
||||
Parameters
|
||||
----------
|
||||
filename : str
|
||||
The filename to write to
|
||||
step : int
|
||||
What step is this?
|
||||
|
||||
"""
|
||||
if have_mpi and h5py.get_config().mpi:
|
||||
kwargs = {'driver': 'mpio', 'comm': comm}
|
||||
else:
|
||||
kwargs = {}
|
||||
|
||||
kwargs['mode'] = "w" if step == 0 else "a"
|
||||
|
||||
with h5py.File(filename, **kwargs) as handle:
|
||||
self._to_hdf5(handle, step)
|
||||
|
||||
def _write_hdf5_metadata(self, handle):
|
||||
"""Writes result metadata in HDF5 file
|
||||
|
||||
Parameters
|
||||
----------
|
||||
handle : h5py.File or h5py.Group
|
||||
An hdf5 file or group type to store this in.
|
||||
|
||||
"""
|
||||
# Create and save the 5 dictionaries:
|
||||
# quantities
|
||||
# self.mat_to_ind -> self.volume (TODO: support for changing volumes)
|
||||
# self.nuc_to_ind
|
||||
# reactions
|
||||
# self.rates[0].nuc_to_ind (can be different from above, above is superset)
|
||||
# self.rates[0].react_to_ind
|
||||
# these are shared by every step of the simulation, and should be deduplicated.
|
||||
|
||||
# Store concentration mat and nuclide dictionaries (along with volumes)
|
||||
|
||||
handle.attrs['version'] = np.array(_VERSION_RESULTS)
|
||||
handle.attrs['filetype'] = np.string_('depletion results')
|
||||
|
||||
mat_list = sorted(self.mat_to_hdf5_ind, key=int)
|
||||
nuc_list = sorted(self.nuc_to_ind)
|
||||
rxn_list = sorted(self.rates[0].index_rx)
|
||||
|
||||
n_mats = self.n_hdf5_mats
|
||||
n_nuc_number = len(nuc_list)
|
||||
n_nuc_rxn = len(self.rates[0].index_nuc)
|
||||
n_rxn = len(rxn_list)
|
||||
n_stages = self.n_stages
|
||||
|
||||
mat_group = handle.create_group("materials")
|
||||
|
||||
for mat in mat_list:
|
||||
mat_single_group = mat_group.create_group(mat)
|
||||
mat_single_group.attrs["index"] = self.mat_to_hdf5_ind[mat]
|
||||
mat_single_group.attrs["volume"] = self.volume[mat]
|
||||
|
||||
nuc_group = handle.create_group("nuclides")
|
||||
|
||||
for nuc in nuc_list:
|
||||
nuc_single_group = nuc_group.create_group(nuc)
|
||||
nuc_single_group.attrs["atom number index"] = self.nuc_to_ind[nuc]
|
||||
if nuc in self.rates[0].index_nuc:
|
||||
nuc_single_group.attrs["reaction rate index"] = self.rates[0].index_nuc[nuc]
|
||||
|
||||
rxn_group = handle.create_group("reactions")
|
||||
|
||||
for rxn in rxn_list:
|
||||
rxn_single_group = rxn_group.create_group(rxn)
|
||||
rxn_single_group.attrs["index"] = self.rates[0].index_rx[rxn]
|
||||
|
||||
# Construct array storage
|
||||
|
||||
handle.create_dataset("number", (1, n_stages, n_mats, n_nuc_number),
|
||||
maxshape=(None, n_stages, n_mats, n_nuc_number),
|
||||
chunks=(1, 1, n_mats, n_nuc_number),
|
||||
dtype='float64')
|
||||
|
||||
handle.create_dataset("reaction rates", (1, n_stages, n_mats, n_nuc_rxn, n_rxn),
|
||||
maxshape=(None, n_stages, n_mats, n_nuc_rxn, n_rxn),
|
||||
chunks=(1, 1, n_mats, n_nuc_rxn, n_rxn),
|
||||
dtype='float64')
|
||||
|
||||
handle.create_dataset("eigenvalues", (1, n_stages),
|
||||
maxshape=(None, n_stages), dtype='float64')
|
||||
|
||||
handle.create_dataset("time", (1, 2), maxshape=(None, 2), dtype='float64')
|
||||
|
||||
def _to_hdf5(self, handle, index):
|
||||
"""Converts results object into an hdf5 object.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
handle : h5py.File or h5py.Group
|
||||
An HDF5 file or group type to store this in.
|
||||
index : int
|
||||
What step is this?
|
||||
|
||||
"""
|
||||
if "/number" not in handle:
|
||||
comm.barrier()
|
||||
self._write_hdf5_metadata(handle)
|
||||
|
||||
comm.barrier()
|
||||
|
||||
# Grab handles
|
||||
number_dset = handle["/number"]
|
||||
rxn_dset = handle["/reaction rates"]
|
||||
eigenvalues_dset = handle["/eigenvalues"]
|
||||
time_dset = handle["/time"]
|
||||
|
||||
# Get number of results stored
|
||||
number_shape = list(number_dset.shape)
|
||||
number_results = number_shape[0]
|
||||
|
||||
new_shape = index + 1
|
||||
|
||||
if number_results < new_shape:
|
||||
# Extend first dimension by 1
|
||||
number_shape[0] = new_shape
|
||||
number_dset.resize(number_shape)
|
||||
|
||||
rxn_shape = list(rxn_dset.shape)
|
||||
rxn_shape[0] = new_shape
|
||||
rxn_dset.resize(rxn_shape)
|
||||
|
||||
eigenvalues_shape = list(eigenvalues_dset.shape)
|
||||
eigenvalues_shape[0] = new_shape
|
||||
eigenvalues_dset.resize(eigenvalues_shape)
|
||||
|
||||
time_shape = list(time_dset.shape)
|
||||
time_shape[0] = new_shape
|
||||
time_dset.resize(time_shape)
|
||||
|
||||
# If nothing to write, just return
|
||||
if len(self.mat_to_ind) == 0:
|
||||
return
|
||||
|
||||
# Add data
|
||||
# Note, for the last step, self.n_stages = 1, even if n_stages != 1.
|
||||
n_stages = self.n_stages
|
||||
inds = [self.mat_to_hdf5_ind[mat] for mat in self.mat_to_ind]
|
||||
low = min(inds)
|
||||
high = max(inds)
|
||||
for i in range(n_stages):
|
||||
number_dset[index, i, low:high+1, :] = self.data[i, :, :]
|
||||
rxn_dset[index, i, low:high+1, :, :] = self.rates[i][:, :, :]
|
||||
if comm.rank == 0:
|
||||
eigenvalues_dset[index, i] = self.k[i]
|
||||
if comm.rank == 0:
|
||||
time_dset[index, :] = self.time
|
||||
|
||||
@classmethod
|
||||
def from_hdf5(cls, handle, step):
|
||||
"""Loads results object from HDF5.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
handle : h5py.File or h5py.Group
|
||||
An HDF5 file or group type to load from.
|
||||
step : int
|
||||
What step is this?
|
||||
|
||||
"""
|
||||
results = cls()
|
||||
|
||||
# Grab handles
|
||||
number_dset = handle["/number"]
|
||||
eigenvalues_dset = handle["/eigenvalues"]
|
||||
time_dset = handle["/time"]
|
||||
|
||||
results.data = number_dset[step, :, :, :]
|
||||
results.k = eigenvalues_dset[step, :]
|
||||
results.time = time_dset[step, :]
|
||||
|
||||
# Reconstruct dictionaries
|
||||
results.volume = OrderedDict()
|
||||
results.mat_to_ind = OrderedDict()
|
||||
results.nuc_to_ind = OrderedDict()
|
||||
rxn_nuc_to_ind = OrderedDict()
|
||||
rxn_to_ind = OrderedDict()
|
||||
|
||||
for mat, mat_handle in handle["/materials"].items():
|
||||
vol = mat_handle.attrs["volume"]
|
||||
ind = mat_handle.attrs["index"]
|
||||
|
||||
results.volume[mat] = vol
|
||||
results.mat_to_ind[mat] = ind
|
||||
|
||||
for nuc, nuc_handle in handle["/nuclides"].items():
|
||||
ind_atom = nuc_handle.attrs["atom number index"]
|
||||
results.nuc_to_ind[nuc] = ind_atom
|
||||
|
||||
if "reaction rate index" in nuc_handle.attrs:
|
||||
rxn_nuc_to_ind[nuc] = nuc_handle.attrs["reaction rate index"]
|
||||
|
||||
for rxn, rxn_handle in handle["/reactions"].items():
|
||||
rxn_to_ind[rxn] = rxn_handle.attrs["index"]
|
||||
|
||||
results.rates = []
|
||||
# Reconstruct reactions
|
||||
for i in range(results.n_stages):
|
||||
rate = ReactionRates(results.mat_to_ind, rxn_nuc_to_ind, rxn_to_ind)
|
||||
|
||||
rate[:] = handle["/reaction rates"][step, i, :, :, :]
|
||||
results.rates.append(rate)
|
||||
|
||||
return results
|
||||
|
||||
@staticmethod
|
||||
def save(op, x, op_results, t, step_ind):
|
||||
"""Creates and writes depletion results to disk
|
||||
|
||||
Parameters
|
||||
----------
|
||||
op : openmc.deplete.TransportOperator
|
||||
The operator used to generate these results.
|
||||
x : list of list of numpy.array
|
||||
The prior x vectors. Indexed [i][cell] using the above equation.
|
||||
op_results : list of openmc.deplete.OperatorResult
|
||||
Results of applying transport operator
|
||||
t : list of float
|
||||
Time indices.
|
||||
step_ind : int
|
||||
Step index.
|
||||
|
||||
"""
|
||||
# Get indexing terms
|
||||
vol_dict, nuc_list, burn_list, full_burn_list = op.get_results_info()
|
||||
|
||||
# Create results
|
||||
stages = len(x)
|
||||
results = Results()
|
||||
results.allocate(vol_dict, nuc_list, burn_list, full_burn_list, stages)
|
||||
|
||||
n_mat = len(burn_list)
|
||||
|
||||
for i in range(stages):
|
||||
for mat_i in range(n_mat):
|
||||
results[i, mat_i, :] = x[i][mat_i][:]
|
||||
|
||||
results.k = [r.k for r in op_results]
|
||||
results.rates = [r.rates for r in op_results]
|
||||
results.time = t
|
||||
|
||||
results.export_to_hdf5("depletion_results.h5", step_ind)
|
||||
105
openmc/deplete/results_list.py
Normal file
105
openmc/deplete/results_list.py
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
import h5py
|
||||
import numpy as np
|
||||
|
||||
from .results import Results, _VERSION_RESULTS
|
||||
from openmc.checkvalue import check_filetype_version
|
||||
|
||||
|
||||
class ResultsList(list):
|
||||
"""A list of openmc.deplete.Results objects
|
||||
|
||||
Parameters
|
||||
----------
|
||||
filename : str
|
||||
The filename to read from.
|
||||
|
||||
"""
|
||||
def __init__(self, filename):
|
||||
super().__init__()
|
||||
with h5py.File(str(filename), "r") as fh:
|
||||
check_filetype_version(fh, 'depletion results', _VERSION_RESULTS[0])
|
||||
|
||||
# Get number of results stored
|
||||
n = fh["number"].value.shape[0]
|
||||
|
||||
for i in range(n):
|
||||
self.append(Results.from_hdf5(fh, i))
|
||||
|
||||
def get_atoms(self, mat, nuc):
|
||||
"""Get nuclide concentration over time from a single material
|
||||
|
||||
Parameters
|
||||
----------
|
||||
mat : str
|
||||
Material name to evaluate
|
||||
nuc : str
|
||||
Nuclide name to evaluate
|
||||
|
||||
Returns
|
||||
-------
|
||||
time : numpy.ndarray
|
||||
Array of times in [s]
|
||||
concentration : numpy.ndarray
|
||||
Total number of atoms for specified nuclide
|
||||
|
||||
"""
|
||||
time = np.empty_like(self)
|
||||
concentration = np.empty_like(self)
|
||||
|
||||
# Evaluate value in each region
|
||||
for i, result in enumerate(self):
|
||||
time[i] = result.time[0]
|
||||
concentration[i] = result[0, mat, nuc]
|
||||
|
||||
return time, concentration
|
||||
|
||||
def get_reaction_rate(self, mat, nuc, rx):
|
||||
"""Get reaction rate in a single material/nuclide over time
|
||||
|
||||
Parameters
|
||||
----------
|
||||
mat : str
|
||||
Material name to evaluate
|
||||
nuc : str
|
||||
Nuclide name to evaluate
|
||||
rx : str
|
||||
Reaction rate to evaluate
|
||||
|
||||
Returns
|
||||
-------
|
||||
time : numpy.ndarray
|
||||
Array of times in [s]
|
||||
rate : numpy.ndarray
|
||||
Array of reaction rates
|
||||
|
||||
"""
|
||||
time = np.empty_like(self)
|
||||
rate = np.empty_like(self)
|
||||
|
||||
# Evaluate value in each region
|
||||
for i, result in enumerate(self):
|
||||
time[i] = result.time[0]
|
||||
rate[i] = result.rates[0].get(mat, nuc, rx) * result[0, mat, nuc]
|
||||
|
||||
return time, rate
|
||||
|
||||
def get_eigenvalue(self):
|
||||
"""Evaluates the eigenvalue from a results list.
|
||||
|
||||
Returns
|
||||
-------
|
||||
time : numpy.ndarray
|
||||
Array of times in [s]
|
||||
eigenvalue : numpy.ndarray
|
||||
k-eigenvalue at each time
|
||||
|
||||
"""
|
||||
time = np.empty_like(self)
|
||||
eigenvalue = np.empty_like(self)
|
||||
|
||||
# Get time/eigenvalue at each point
|
||||
for i, result in enumerate(self):
|
||||
time[i] = result.time[0]
|
||||
eigenvalue[i] = result.k[0]
|
||||
|
||||
return time, eigenvalue
|
||||
|
|
@ -1,8 +1,6 @@
|
|||
from collections import OrderedDict
|
||||
import re
|
||||
import os
|
||||
|
||||
from six import string_types
|
||||
from xml.etree import ElementTree as ET
|
||||
|
||||
import openmc
|
||||
|
|
@ -10,7 +8,7 @@ import openmc.checkvalue as cv
|
|||
from openmc.data import NATURAL_ABUNDANCE, atomic_mass
|
||||
|
||||
|
||||
class Element(object):
|
||||
class Element(str):
|
||||
"""A natural element that auto-expands to add the isotopes of an element to
|
||||
a material in their natural abundance. Internally, the OpenMC Python API
|
||||
expands the natural element into isotopes only when the materials.xml file
|
||||
|
|
@ -25,73 +23,17 @@ class Element(object):
|
|||
----------
|
||||
name : str
|
||||
Chemical symbol of the element, e.g. Pu
|
||||
scattering : {'data', 'iso-in-lab', None}
|
||||
The type of angular scattering distribution to use
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, name=''):
|
||||
# Initialize class attributes
|
||||
self._name = ''
|
||||
self._scattering = None
|
||||
|
||||
# Set class attributes
|
||||
self.name = name
|
||||
|
||||
def __eq__(self, other):
|
||||
if isinstance(other, Element):
|
||||
if self.name != other.name:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
elif isinstance(other, string_types) and other == self.name:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self == other
|
||||
|
||||
def __gt__(self, other):
|
||||
return repr(self) > repr(other)
|
||||
|
||||
def __lt__(self, other):
|
||||
return not self > other
|
||||
|
||||
def __hash__(self):
|
||||
return hash(repr(self))
|
||||
|
||||
def __repr__(self):
|
||||
string = 'Element - {0}\n'.format(self._name)
|
||||
if self.scattering is not None:
|
||||
string += '{0: <16}{1}{2}\n'.format('\tscattering', '=\t',
|
||||
self.scattering)
|
||||
|
||||
return string
|
||||
def __new__(cls, name):
|
||||
cv.check_type('element name', name, str)
|
||||
cv.check_length('element name', name, 1, 2)
|
||||
return super().__new__(cls, name)
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def scattering(self):
|
||||
return self._scattering
|
||||
|
||||
@name.setter
|
||||
def name(self, name):
|
||||
cv.check_type('element name', name, string_types)
|
||||
cv.check_length('element name', name, 1, 2)
|
||||
self._name = name
|
||||
|
||||
@scattering.setter
|
||||
def scattering(self, scattering):
|
||||
|
||||
if not scattering in ['data', 'iso-in-lab', None]:
|
||||
msg = 'Unable to set scattering for Element to {0} which ' \
|
||||
'is not "data", "iso-in-lab", or None'.format(scattering)
|
||||
raise ValueError(msg)
|
||||
|
||||
self._scattering = scattering
|
||||
return self
|
||||
|
||||
def expand(self, percent, percent_type, enrichment=None,
|
||||
cross_sections=None):
|
||||
|
|
@ -121,8 +63,8 @@ class Element(object):
|
|||
-------
|
||||
isotopes : list
|
||||
Naturally-occurring isotopes of the element. Each item of the list
|
||||
is a tuple consisting of an openmc.Nuclide instance and the natural
|
||||
abundance of the isotope.
|
||||
is a tuple consisting of a nuclide string, the atom/weight percent,
|
||||
and the string 'ao' or 'wo'.
|
||||
|
||||
Notes
|
||||
-----
|
||||
|
|
@ -138,7 +80,7 @@ class Element(object):
|
|||
# Get the nuclides present in nature
|
||||
natural_nuclides = set()
|
||||
for nuclide in sorted(NATURAL_ABUNDANCE.keys()):
|
||||
if re.match(r'{}\d+'.format(self.name), nuclide):
|
||||
if re.match(r'{}\d+'.format(self), nuclide):
|
||||
natural_nuclides.add(nuclide)
|
||||
|
||||
# Create dict to store the expanded nuclides and abundances
|
||||
|
|
@ -158,7 +100,7 @@ class Element(object):
|
|||
root = tree.getroot()
|
||||
for child in root:
|
||||
nuclide = child.attrib['materials']
|
||||
if re.match(r'{}\d+'.format(self.name), nuclide) and \
|
||||
if re.match(r'{}\d+'.format(self), nuclide) and \
|
||||
'_m' not in nuclide:
|
||||
library_nuclides.add(nuclide)
|
||||
|
||||
|
|
@ -179,14 +121,14 @@ class Element(object):
|
|||
# 0 nuclide is present. If so, set the abundance to 1 for this
|
||||
# nuclide. Else, raise an error.
|
||||
elif len(mutual_nuclides) == 0:
|
||||
nuclide_0 = self.name + '0'
|
||||
nuclide_0 = self + '0'
|
||||
if nuclide_0 in library_nuclides:
|
||||
abundances[nuclide_0] = 1.0
|
||||
else:
|
||||
msg = 'Unable to expand element {0} because the cross '\
|
||||
'section library provided does not contain any of '\
|
||||
'the natural isotopes for that element.'\
|
||||
.format(self.name)
|
||||
.format(self)
|
||||
raise ValueError(msg)
|
||||
|
||||
# If some, but not all, natural nuclides are in the library, add
|
||||
|
|
@ -261,8 +203,6 @@ class Element(object):
|
|||
# Create a list of the isotopes in this element
|
||||
isotopes = []
|
||||
for nuclide, abundance in abundances.items():
|
||||
nuc = openmc.Nuclide(nuclide)
|
||||
nuc.scattering = self.scattering
|
||||
isotopes.append((nuc, percent * abundance, percent_type))
|
||||
isotopes.append((nuclide, percent * abundance, percent_type))
|
||||
|
||||
return isotopes
|
||||
|
|
|
|||
|
|
@ -573,21 +573,21 @@ def slab_mg(reps=None, as_macro=True):
|
|||
for mat in mat_names:
|
||||
for rep in reps:
|
||||
i += 1
|
||||
name = mat + '_' + rep
|
||||
xs.append(name)
|
||||
if as_macro:
|
||||
xs.append(openmc.Macroscopic(mat + '_' + rep))
|
||||
m = openmc.Material(name=str(i))
|
||||
m.set_density('macro', 1.)
|
||||
m.add_macroscopic(xs[-1])
|
||||
m.add_macroscopic(name)
|
||||
else:
|
||||
xs.append(openmc.Nuclide(mat + '_' + rep))
|
||||
m = openmc.Material(name=str(i))
|
||||
m.set_density('atom/b-cm', 1.)
|
||||
m.add_nuclide(xs[-1].name, 1.0, 'ao')
|
||||
m.add_nuclide(name, 1.0, 'ao')
|
||||
model.materials.append(m)
|
||||
|
||||
# Define the materials file
|
||||
model.xs_data = xs
|
||||
model.materials.cross_sections = "../1d_mgxs.h5"
|
||||
model.materials.cross_sections = "../../1d_mgxs.h5"
|
||||
|
||||
# Define surfaces.
|
||||
# Assembly/Problem Boundary
|
||||
|
|
|
|||
|
|
@ -1,10 +1,7 @@
|
|||
from __future__ import print_function
|
||||
from collections import Iterable
|
||||
from collections.abc import Iterable
|
||||
import subprocess
|
||||
from numbers import Integral
|
||||
|
||||
from six import string_types
|
||||
|
||||
import openmc
|
||||
from openmc import VolumeCalculation
|
||||
|
||||
|
|
@ -15,18 +12,22 @@ def _run(args, output, cwd):
|
|||
stderr=subprocess.STDOUT, universal_newlines=True)
|
||||
|
||||
# Capture and re-print OpenMC output in real-time
|
||||
lines = []
|
||||
while True:
|
||||
# If OpenMC is finished, break loop
|
||||
line = p.stdout.readline()
|
||||
if not line and p.poll() is not None:
|
||||
break
|
||||
|
||||
lines.append(line)
|
||||
if output:
|
||||
# If user requested output, print to screen
|
||||
print(line, end='')
|
||||
|
||||
# Return the returncode (integer, zero if no problems encountered)
|
||||
return p.returncode
|
||||
# Raise an exception if return status is non-zero
|
||||
if p.returncode != 0:
|
||||
raise subprocess.CalledProcessError(p.returncode, ' '.join(args),
|
||||
''.join(lines))
|
||||
|
||||
|
||||
def plot_geometry(output=True, openmc_exec='openmc', cwd='.'):
|
||||
|
|
@ -41,8 +42,13 @@ def plot_geometry(output=True, openmc_exec='openmc', cwd='.'):
|
|||
cwd : str, optional
|
||||
Path to working directory to run in
|
||||
|
||||
Raises
|
||||
------
|
||||
subprocess.CalledProcessError
|
||||
If the `openmc` executable returns a non-zero status
|
||||
|
||||
"""
|
||||
return _run([openmc_exec, '-p'], output, cwd)
|
||||
_run([openmc_exec, '-p'], output, cwd)
|
||||
|
||||
|
||||
def plot_inline(plots, openmc_exec='openmc', cwd='.', convert_exec='convert'):
|
||||
|
|
@ -63,6 +69,11 @@ def plot_inline(plots, openmc_exec='openmc', cwd='.', convert_exec='convert'):
|
|||
convert_exec : str, optional
|
||||
Command that can convert PPM files into PNG files
|
||||
|
||||
Raises
|
||||
------
|
||||
subprocess.CalledProcessError
|
||||
If the `openmc` executable returns a non-zero status
|
||||
|
||||
"""
|
||||
from IPython.display import Image, display
|
||||
|
||||
|
|
@ -121,6 +132,11 @@ def calculate_volumes(threads=None, output=True, cwd='.',
|
|||
Path to working directory to run in. Defaults to the current working
|
||||
directory.
|
||||
|
||||
Raises
|
||||
------
|
||||
subprocess.CalledProcessError
|
||||
If the `openmc` executable returns a non-zero status
|
||||
|
||||
See Also
|
||||
--------
|
||||
openmc.VolumeCalculation
|
||||
|
|
@ -133,7 +149,7 @@ def calculate_volumes(threads=None, output=True, cwd='.',
|
|||
if mpi_args is not None:
|
||||
args = mpi_args + args
|
||||
|
||||
return _run(args, output, cwd)
|
||||
_run(args, output, cwd)
|
||||
|
||||
|
||||
def run(particles=None, threads=None, geometry_debug=False,
|
||||
|
|
@ -167,8 +183,12 @@ def run(particles=None, threads=None, geometry_debug=False,
|
|||
MPI execute command and any additional MPI arguments to pass,
|
||||
e.g. ['mpiexec', '-n', '8'].
|
||||
|
||||
"""
|
||||
Raises
|
||||
------
|
||||
subprocess.CalledProcessError
|
||||
If the `openmc` executable returns a non-zero status
|
||||
|
||||
"""
|
||||
args = [openmc_exec]
|
||||
|
||||
if isinstance(particles, Integral) and particles > 0:
|
||||
|
|
@ -180,7 +200,7 @@ def run(particles=None, threads=None, geometry_debug=False,
|
|||
if geometry_debug:
|
||||
args.append('-g')
|
||||
|
||||
if isinstance(restart_file, string_types):
|
||||
if isinstance(restart_file, str):
|
||||
args += ['-r', restart_file]
|
||||
|
||||
if tracks:
|
||||
|
|
@ -189,4 +209,4 @@ def run(particles=None, threads=None, geometry_debug=False,
|
|||
if mpi_args is not None:
|
||||
args = mpi_args + args
|
||||
|
||||
return _run(args, output, cwd)
|
||||
_run(args, output, cwd)
|
||||
|
|
|
|||
366
openmc/filter.py
366
openmc/filter.py
|
|
@ -1,18 +1,21 @@
|
|||
from __future__ import division
|
||||
from abc import ABCMeta
|
||||
from collections import Iterable, OrderedDict
|
||||
import copy
|
||||
from functools import reduce
|
||||
import hashlib
|
||||
from numbers import Real, Integral
|
||||
import operator
|
||||
from xml.etree import ElementTree as ET
|
||||
|
||||
from six import add_metaclass
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
|
||||
import openmc
|
||||
import openmc.checkvalue as cv
|
||||
from .cell import Cell
|
||||
from .material import Material
|
||||
from .mixin import IDManagerMixin
|
||||
from .universe import Universe
|
||||
|
||||
|
||||
_FILTER_TYPES = ['universe', 'material', 'cell', 'cellborn', 'surface',
|
||||
|
|
@ -63,12 +66,10 @@ class FilterMeta(ABCMeta):
|
|||
namespace[func_name].__doc__ = old_doc
|
||||
|
||||
# Make the class.
|
||||
return super(FilterMeta, cls).__new__(cls, name, bases, namespace,
|
||||
**kwargs)
|
||||
return super().__new__(cls, name, bases, namespace, **kwargs)
|
||||
|
||||
|
||||
@add_metaclass(FilterMeta)
|
||||
class Filter(IDManagerMixin):
|
||||
class Filter(IDManagerMixin, metaclass=FilterMeta):
|
||||
"""Tally modifier that describes phase-space and other characteristics.
|
||||
|
||||
Parameters
|
||||
|
|
@ -88,9 +89,6 @@ class Filter(IDManagerMixin):
|
|||
Unique identifier for the filter
|
||||
num_bins : Integral
|
||||
The number of filter bins
|
||||
stride : Integral
|
||||
The number of filter, nuclide and score bins within each of this
|
||||
filter's bins.
|
||||
|
||||
"""
|
||||
|
||||
|
|
@ -100,8 +98,6 @@ class Filter(IDManagerMixin):
|
|||
def __init__(self, bins, filter_id=None):
|
||||
self.bins = bins
|
||||
self.id = filter_id
|
||||
self._num_bins = 0
|
||||
self._stride = None
|
||||
|
||||
def __eq__(self, other):
|
||||
if type(self) is not type(other):
|
||||
|
|
@ -175,8 +171,8 @@ class Filter(IDManagerMixin):
|
|||
# If the HDF5 'type' variable matches this class's short_name, then
|
||||
# there is no overriden from_hdf5 method. Pass the bins to __init__.
|
||||
if group['type'].value.decode() == cls.short_name.lower():
|
||||
out = cls(group['bins'].value, filter_id)
|
||||
out.num_bins = group['n_bins'].value
|
||||
out = cls(group['bins'].value, filter_id=filter_id)
|
||||
out._num_bins = group['n_bins'].value
|
||||
return out
|
||||
|
||||
# Search through all subclasses and find the one matching the HDF5
|
||||
|
|
@ -194,11 +190,7 @@ class Filter(IDManagerMixin):
|
|||
|
||||
@property
|
||||
def num_bins(self):
|
||||
return self._num_bins
|
||||
|
||||
@property
|
||||
def stride(self):
|
||||
return self._stride
|
||||
return len(self.bins)
|
||||
|
||||
@bins.setter
|
||||
def bins(self, bins):
|
||||
|
|
@ -210,22 +202,6 @@ class Filter(IDManagerMixin):
|
|||
|
||||
self._bins = bins
|
||||
|
||||
@num_bins.setter
|
||||
def num_bins(self, num_bins):
|
||||
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
|
||||
|
||||
@stride.setter
|
||||
def stride(self, stride):
|
||||
cv.check_type('filter stride', stride, Integral)
|
||||
if stride < 0:
|
||||
msg = 'Unable to set stride "{0}" for a "{1}" since it ' \
|
||||
'is a negative value'.format(stride, type(self))
|
||||
raise ValueError(msg)
|
||||
|
||||
self._stride = stride
|
||||
|
||||
def check_bins(self, bins):
|
||||
"""Make sure given bins are valid for this filter.
|
||||
|
||||
|
|
@ -272,11 +248,7 @@ class Filter(IDManagerMixin):
|
|||
Whether the filter can be merged
|
||||
|
||||
"""
|
||||
|
||||
if type(self) is not type(other):
|
||||
return False
|
||||
|
||||
return True
|
||||
return type(self) is type(other)
|
||||
|
||||
def merge(self, other):
|
||||
"""Merge this filter with another.
|
||||
|
|
@ -404,7 +376,7 @@ class Filter(IDManagerMixin):
|
|||
# Return a 1-tuple of the bin.
|
||||
return (self.bins[bin_index],)
|
||||
|
||||
def get_pandas_dataframe(self, data_size, **kwargs):
|
||||
def get_pandas_dataframe(self, data_size, stride, **kwargs):
|
||||
"""Builds a Pandas DataFrame for the Filter's bins.
|
||||
|
||||
This method constructs a Pandas DataFrame object for the filter with
|
||||
|
|
@ -413,13 +385,15 @@ class Filter(IDManagerMixin):
|
|||
|
||||
Parameters
|
||||
----------
|
||||
data_size : Integral
|
||||
data_size : int
|
||||
The total number of bins in the tally corresponding to this filter
|
||||
stride : int
|
||||
Stride in memory for the filter
|
||||
|
||||
Keyword arguments
|
||||
-----------------
|
||||
paths : bool
|
||||
Only used for DistirbcellFilter. If True (default), expand
|
||||
Only used for DistribcellFilter. If True (default), expand
|
||||
distribcell indices into multi-index columns describing the path
|
||||
to that distribcell through the CSG tree. NOTE: This option assumes
|
||||
that all distribcell paths are of the same length and do not have
|
||||
|
|
@ -433,11 +407,6 @@ class Filter(IDManagerMixin):
|
|||
the total number of bins in the corresponding tally, with the filter
|
||||
bin appropriately tiled to map to the corresponding tally bins.
|
||||
|
||||
Raises
|
||||
------
|
||||
ImportError
|
||||
When Pandas is not installed
|
||||
|
||||
See also
|
||||
--------
|
||||
Tally.get_pandas_dataframe(), CrossFilter.get_pandas_dataframe()
|
||||
|
|
@ -446,7 +415,7 @@ class Filter(IDManagerMixin):
|
|||
# Initialize Pandas DataFrame
|
||||
df = pd.DataFrame()
|
||||
|
||||
filter_bins = np.repeat(self.bins, self.stride)
|
||||
filter_bins = np.repeat(self.bins, stride)
|
||||
tile_factor = data_size // len(filter_bins)
|
||||
filter_bins = np.tile(filter_bins, tile_factor)
|
||||
df = pd.concat([df, pd.DataFrame(
|
||||
|
|
@ -457,23 +426,15 @@ class Filter(IDManagerMixin):
|
|||
|
||||
class WithIDFilter(Filter):
|
||||
"""Abstract parent for filters of types with ids (Cell, Material, etc.)."""
|
||||
@property
|
||||
def num_bins(self):
|
||||
return len(self.bins)
|
||||
|
||||
# Since num_bins property is declared, also need a num_bins.setter, but
|
||||
# we don't want it to do anything since num_bins is completely determined
|
||||
# by len(self.bins). We also don't want to raise an error because that
|
||||
# makes importing from HDF5 more complicated.
|
||||
@num_bins.setter
|
||||
def num_bins(self, num_bins): pass
|
||||
|
||||
def _smart_set_bins(self, bins, bin_type):
|
||||
@Filter.bins.setter
|
||||
def bins(self, bins):
|
||||
# Format the bins as a 1D numpy array.
|
||||
bins = np.atleast_1d(bins)
|
||||
|
||||
# Check the bin values.
|
||||
cv.check_iterable_type('filter bins', bins, (Integral, bin_type))
|
||||
cv.check_iterable_type('filter bins', bins,
|
||||
(Integral, self.expected_type))
|
||||
for edge in bins:
|
||||
if isinstance(edge, Integral):
|
||||
cv.check_greater_than('filter bin', edge, 0, equality=True)
|
||||
|
|
@ -504,18 +465,9 @@ class UniverseFilter(WithIDFilter):
|
|||
Unique identifier for the filter
|
||||
num_bins : Integral
|
||||
The number of filter bins
|
||||
stride : Integral
|
||||
The number of filter, nuclide and score bins within each of this
|
||||
filter's bins.
|
||||
|
||||
"""
|
||||
@property
|
||||
def bins(self):
|
||||
return self._bins
|
||||
|
||||
@bins.setter
|
||||
def bins(self, bins):
|
||||
self._smart_set_bins(bins, openmc.Universe)
|
||||
expected_type = Universe
|
||||
|
||||
|
||||
class MaterialFilter(WithIDFilter):
|
||||
|
|
@ -537,18 +489,9 @@ class MaterialFilter(WithIDFilter):
|
|||
Unique identifier for the filter
|
||||
num_bins : Integral
|
||||
The number of filter bins
|
||||
stride : Integral
|
||||
The number of filter, nuclide and score bins within each of this
|
||||
filter's bins.
|
||||
|
||||
"""
|
||||
@property
|
||||
def bins(self):
|
||||
return self._bins
|
||||
|
||||
@bins.setter
|
||||
def bins(self, bins):
|
||||
self._smart_set_bins(bins, openmc.Material)
|
||||
expected_type = Material
|
||||
|
||||
|
||||
class ParticleFilter(WithIDFilter):
|
||||
|
|
@ -612,18 +555,9 @@ class CellFilter(WithIDFilter):
|
|||
Unique identifier for the filter
|
||||
num_bins : Integral
|
||||
The number of filter bins
|
||||
stride : Integral
|
||||
The number of filter, nuclide and score bins within each of this
|
||||
filter's bins.
|
||||
|
||||
"""
|
||||
@property
|
||||
def bins(self):
|
||||
return self._bins
|
||||
|
||||
@bins.setter
|
||||
def bins(self, bins):
|
||||
self._smart_set_bins(bins, openmc.Cell)
|
||||
expected_type = Cell
|
||||
|
||||
|
||||
class CellFromFilter(WithIDFilter):
|
||||
|
|
@ -645,18 +579,9 @@ class CellFromFilter(WithIDFilter):
|
|||
Unique identifier for the filter
|
||||
num_bins : Integral
|
||||
The number of filter bins
|
||||
stride : Integral
|
||||
The number of filter, nuclide and score bins within each of this
|
||||
filter's bins.
|
||||
|
||||
"""
|
||||
@property
|
||||
def bins(self):
|
||||
return self._bins
|
||||
|
||||
@bins.setter
|
||||
def bins(self, bins):
|
||||
self._smart_set_bins(bins, openmc.Cell)
|
||||
expected_type = Cell
|
||||
|
||||
|
||||
class CellbornFilter(WithIDFilter):
|
||||
|
|
@ -678,18 +603,9 @@ class CellbornFilter(WithIDFilter):
|
|||
Unique identifier for the filter
|
||||
num_bins : Integral
|
||||
The number of filter bins
|
||||
stride : Integral
|
||||
The number of filter, nuclide and score bins within each of this
|
||||
filter's bins.
|
||||
|
||||
"""
|
||||
@property
|
||||
def bins(self):
|
||||
return self._bins
|
||||
|
||||
@bins.setter
|
||||
def bins(self, bins):
|
||||
self._smart_set_bins(bins, openmc.Cell)
|
||||
expected_type = Cell
|
||||
|
||||
|
||||
class SurfaceFilter(Filter):
|
||||
|
|
@ -712,20 +628,9 @@ class SurfaceFilter(Filter):
|
|||
Unique identifier for the filter
|
||||
num_bins : Integral
|
||||
The number of filter bins
|
||||
stride : Integral
|
||||
The number of filter, nuclide and score bins within each of this
|
||||
filter's bins.
|
||||
|
||||
"""
|
||||
@property
|
||||
def bins(self):
|
||||
return self._bins
|
||||
|
||||
@property
|
||||
def num_bins(self):
|
||||
return len(self.bins)
|
||||
|
||||
@bins.setter
|
||||
@Filter.bins.setter
|
||||
def bins(self, bins):
|
||||
# Format the bins as a 1D numpy array.
|
||||
bins = np.atleast_1d(bins)
|
||||
|
|
@ -737,10 +642,14 @@ class SurfaceFilter(Filter):
|
|||
|
||||
self._bins = bins
|
||||
|
||||
@num_bins.setter
|
||||
def num_bins(self, num_bins): pass
|
||||
@property
|
||||
def num_bins(self):
|
||||
# Need to handle number of bins carefully -- for surface current
|
||||
# tallies, the number of bins depends on the mesh, which we don't have a
|
||||
# reference to in this filter
|
||||
return self._num_bins
|
||||
|
||||
def get_pandas_dataframe(self, data_size, **kwargs):
|
||||
def get_pandas_dataframe(self, data_size, stride, **kwargs):
|
||||
"""Builds a Pandas DataFrame for the Filter's bins.
|
||||
|
||||
This method constructs a Pandas DataFrame object for the filter with
|
||||
|
|
@ -749,8 +658,10 @@ class SurfaceFilter(Filter):
|
|||
|
||||
Parameters
|
||||
----------
|
||||
data_size : Integral
|
||||
data_size : int
|
||||
The total number of bins in the tally corresponding to this filter
|
||||
stride : int
|
||||
Stride in memory for the filter
|
||||
|
||||
Returns
|
||||
-------
|
||||
|
|
@ -761,11 +672,6 @@ class SurfaceFilter(Filter):
|
|||
the corresponding tally, with the filter bin appropriately tiled to
|
||||
map to the corresponding tally bins.
|
||||
|
||||
Raises
|
||||
------
|
||||
ImportError
|
||||
When Pandas is not installed
|
||||
|
||||
See also
|
||||
--------
|
||||
Tally.get_pandas_dataframe(), CrossFilter.get_pandas_dataframe()
|
||||
|
|
@ -774,7 +680,7 @@ class SurfaceFilter(Filter):
|
|||
# Initialize Pandas DataFrame
|
||||
df = pd.DataFrame()
|
||||
|
||||
filter_bins = np.repeat(self.bins, self.stride)
|
||||
filter_bins = np.repeat(self.bins, stride)
|
||||
tile_factor = data_size // len(filter_bins)
|
||||
filter_bins = np.tile(filter_bins, tile_factor)
|
||||
filter_bins = [_CURRENT_NAMES[x] for x in filter_bins]
|
||||
|
|
@ -804,15 +710,12 @@ class MeshFilter(Filter):
|
|||
Unique identifier for the filter
|
||||
num_bins : Integral
|
||||
The number of filter bins
|
||||
stride : Integral
|
||||
The number of filter, nuclide and score bins within each of this
|
||||
filter's bins.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, mesh, filter_id=None):
|
||||
self.mesh = mesh
|
||||
super(MeshFilter, self).__init__(mesh.id, filter_id)
|
||||
super().__init__(mesh.id, filter_id)
|
||||
|
||||
@classmethod
|
||||
def from_hdf5(cls, group, **kwargs):
|
||||
|
|
@ -829,8 +732,8 @@ class MeshFilter(Filter):
|
|||
mesh_obj = kwargs['meshes'][mesh_id]
|
||||
filter_id = int(group.name.split('/')[-1].lstrip('filter '))
|
||||
|
||||
out = cls(mesh_obj, filter_id)
|
||||
out.num_bins = group['n_bins'].value
|
||||
out = cls(mesh_obj, filter_id=filter_id)
|
||||
out._num_bins = group['n_bins'].value
|
||||
|
||||
return out
|
||||
|
||||
|
|
@ -844,6 +747,13 @@ class MeshFilter(Filter):
|
|||
self._mesh = mesh
|
||||
self.bins = mesh.id
|
||||
|
||||
@property
|
||||
def num_bins(self):
|
||||
try:
|
||||
return self._num_bins
|
||||
except AttributeError:
|
||||
return reduce(operator.mul, self.mesh.dimension)
|
||||
|
||||
def check_bins(self, bins):
|
||||
if not len(bins) == 1:
|
||||
msg = 'Unable to add bins "{0}" to a MeshFilter since ' \
|
||||
|
|
@ -898,7 +808,7 @@ class MeshFilter(Filter):
|
|||
y = bin_index - (x * ny)
|
||||
return (x, y)
|
||||
|
||||
def get_pandas_dataframe(self, data_size, **kwargs):
|
||||
def get_pandas_dataframe(self, data_size, stride, **kwargs):
|
||||
"""Builds a Pandas DataFrame for the Filter's bins.
|
||||
|
||||
This method constructs a Pandas DataFrame object for the filter with
|
||||
|
|
@ -907,8 +817,10 @@ class MeshFilter(Filter):
|
|||
|
||||
Parameters
|
||||
----------
|
||||
data_size : Integral
|
||||
data_size : int
|
||||
The total number of bins in the tally corresponding to this filter
|
||||
stride : int
|
||||
Stride in memory for the filter
|
||||
|
||||
Returns
|
||||
-------
|
||||
|
|
@ -919,11 +831,6 @@ class MeshFilter(Filter):
|
|||
corresponding tally, with the filter bin appropriately tiled to map
|
||||
to the corresponding tally bins.
|
||||
|
||||
Raises
|
||||
------
|
||||
ImportError
|
||||
When Pandas is not installed
|
||||
|
||||
See also
|
||||
--------
|
||||
Tally.get_pandas_dataframe(), CrossFilter.get_pandas_dataframe()
|
||||
|
|
@ -950,7 +857,7 @@ class MeshFilter(Filter):
|
|||
|
||||
# Generate multi-index sub-column for x-axis
|
||||
filter_bins = np.arange(1, nx + 1)
|
||||
repeat_factor = ny * nz * self.stride
|
||||
repeat_factor = ny * nz * stride
|
||||
filter_bins = np.repeat(filter_bins, repeat_factor)
|
||||
tile_factor = data_size // len(filter_bins)
|
||||
filter_bins = np.tile(filter_bins, tile_factor)
|
||||
|
|
@ -958,7 +865,7 @@ class MeshFilter(Filter):
|
|||
|
||||
# Generate multi-index sub-column for y-axis
|
||||
filter_bins = np.arange(1, ny + 1)
|
||||
repeat_factor = nz * self.stride
|
||||
repeat_factor = nz * stride
|
||||
filter_bins = np.repeat(filter_bins, repeat_factor)
|
||||
tile_factor = data_size // len(filter_bins)
|
||||
filter_bins = np.tile(filter_bins, tile_factor)
|
||||
|
|
@ -966,7 +873,7 @@ class MeshFilter(Filter):
|
|||
|
||||
# Generate multi-index sub-column for z-axis
|
||||
filter_bins = np.arange(1, nz + 1)
|
||||
repeat_factor = self.stride
|
||||
repeat_factor = stride
|
||||
filter_bins = np.repeat(filter_bins, repeat_factor)
|
||||
tile_factor = data_size // len(filter_bins)
|
||||
filter_bins = np.tile(filter_bins, tile_factor)
|
||||
|
|
@ -994,11 +901,8 @@ class RealFilter(Filter):
|
|||
A grid of bin values.
|
||||
id : int
|
||||
Unique identifier for the filter
|
||||
num_bins : Integral
|
||||
num_bins : int
|
||||
The number of filter bins
|
||||
stride : Integral
|
||||
The number of filter, nuclide and score bins within each of this
|
||||
filter's bins.
|
||||
|
||||
"""
|
||||
|
||||
|
|
@ -1008,18 +912,12 @@ class RealFilter(Filter):
|
|||
# This logic is used when merging tallies with real filters
|
||||
return self.bins[0] >= other.bins[-1]
|
||||
else:
|
||||
return super(RealFilter, self).__gt__(other)
|
||||
return super().__gt__(other)
|
||||
|
||||
@property
|
||||
def num_bins(self):
|
||||
return len(self.bins) - 1
|
||||
|
||||
@num_bins.setter
|
||||
def num_bins(self, num_bins):
|
||||
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
|
||||
|
||||
def can_merge(self, other):
|
||||
if type(self) is not type(other):
|
||||
return False
|
||||
|
|
@ -1105,11 +1003,8 @@ class EnergyFilter(RealFilter):
|
|||
A grid of energy values in eV.
|
||||
id : int
|
||||
Unique identifier for the filter
|
||||
num_bins : Integral
|
||||
num_bins : int
|
||||
The number of filter bins
|
||||
stride : Integral
|
||||
The number of filter, nuclide and score bins within each of this
|
||||
filter's bins.
|
||||
|
||||
"""
|
||||
|
||||
|
|
@ -1144,7 +1039,7 @@ class EnergyFilter(RealFilter):
|
|||
'increasing'.format(bins, type(self))
|
||||
raise ValueError(msg)
|
||||
|
||||
def get_pandas_dataframe(self, data_size, **kwargs):
|
||||
def get_pandas_dataframe(self, data_size, stride, **kwargs):
|
||||
"""Builds a Pandas DataFrame for the Filter's bins.
|
||||
|
||||
This method constructs a Pandas DataFrame object for the filter with
|
||||
|
|
@ -1153,8 +1048,10 @@ class EnergyFilter(RealFilter):
|
|||
|
||||
Parameters
|
||||
----------
|
||||
data_size : Integral
|
||||
data_size : int
|
||||
The total number of bins in the tally corresponding to this filter
|
||||
stride : int
|
||||
Stride in memory for the filter
|
||||
|
||||
Returns
|
||||
-------
|
||||
|
|
@ -1165,11 +1062,6 @@ class EnergyFilter(RealFilter):
|
|||
corresponding tally, with the filter bin appropriately tiled to map
|
||||
to the corresponding tally bins.
|
||||
|
||||
Raises
|
||||
------
|
||||
ImportError
|
||||
When Pandas is not installed
|
||||
|
||||
See also
|
||||
--------
|
||||
Tally.get_pandas_dataframe(), CrossFilter.get_pandas_dataframe()
|
||||
|
|
@ -1180,8 +1072,8 @@ class EnergyFilter(RealFilter):
|
|||
|
||||
# Extract the lower and upper energy bounds, then repeat and tile
|
||||
# them as necessary to account for other filters.
|
||||
lo_bins = np.repeat(self.bins[:-1], self.stride)
|
||||
hi_bins = np.repeat(self.bins[1:], self.stride)
|
||||
lo_bins = np.repeat(self.bins[:-1], stride)
|
||||
hi_bins = np.repeat(self.bins[1:], stride)
|
||||
tile_factor = data_size // len(lo_bins)
|
||||
lo_bins = np.tile(lo_bins, tile_factor)
|
||||
hi_bins = np.tile(hi_bins, tile_factor)
|
||||
|
|
@ -1209,11 +1101,8 @@ class EnergyoutFilter(EnergyFilter):
|
|||
A grid of energy values in eV.
|
||||
id : int
|
||||
Unique identifier for the filter
|
||||
num_bins : Integral
|
||||
num_bins : int
|
||||
The number of filter bins
|
||||
stride : Integral
|
||||
The number of filter, nuclide and score bins within each of this
|
||||
filter's bins.
|
||||
|
||||
"""
|
||||
|
||||
|
|
@ -1271,11 +1160,8 @@ class DistribcellFilter(Filter):
|
|||
An iterable with one element---the ID of the distributed Cell.
|
||||
id : int
|
||||
Unique identifier for the filter
|
||||
num_bins : Integral
|
||||
num_bins : int
|
||||
The number of filter bins
|
||||
stride : Integral
|
||||
The number of filter, nuclide and score bins within each of this
|
||||
filter's bins.
|
||||
paths : list of str
|
||||
The paths traversed through the CSG tree to reach each distribcell
|
||||
instance (for 'distribcell' filters only)
|
||||
|
|
@ -1284,7 +1170,7 @@ class DistribcellFilter(Filter):
|
|||
|
||||
def __init__(self, cell, filter_id=None):
|
||||
self._paths = None
|
||||
super(DistribcellFilter, self).__init__(cell, filter_id)
|
||||
super().__init__(cell, filter_id)
|
||||
|
||||
@classmethod
|
||||
def from_hdf5(cls, group, **kwargs):
|
||||
|
|
@ -1295,20 +1181,22 @@ class DistribcellFilter(Filter):
|
|||
|
||||
filter_id = int(group.name.split('/')[-1].lstrip('filter '))
|
||||
|
||||
out = cls(group['bins'].value, filter_id)
|
||||
out.num_bins = group['n_bins'].value
|
||||
out = cls(group['bins'].value, filter_id=filter_id)
|
||||
out._num_bins = group['n_bins'].value
|
||||
|
||||
return out
|
||||
|
||||
@property
|
||||
def bins(self):
|
||||
return self._bins
|
||||
def num_bins(self):
|
||||
# Need to handle number of bins carefully -- for distribcell tallies, we
|
||||
# need to know how many instances of the cell there are
|
||||
return self._num_bins
|
||||
|
||||
@property
|
||||
def paths(self):
|
||||
return self._paths
|
||||
|
||||
@bins.setter
|
||||
@Filter.bins.setter
|
||||
def bins(self, bins):
|
||||
# Format the bins as a 1D numpy array.
|
||||
bins = np.atleast_1d(bins)
|
||||
|
|
@ -1340,7 +1228,7 @@ class DistribcellFilter(Filter):
|
|||
# the Cell in the Geometry (consecutive integers starting at 0).
|
||||
return filter_bin
|
||||
|
||||
def get_pandas_dataframe(self, data_size, **kwargs):
|
||||
def get_pandas_dataframe(self, data_size, stride, **kwargs):
|
||||
"""Builds a Pandas DataFrame for the Filter's bins.
|
||||
|
||||
This method constructs a Pandas DataFrame object for the filter with
|
||||
|
|
@ -1349,8 +1237,10 @@ class DistribcellFilter(Filter):
|
|||
|
||||
Parameters
|
||||
----------
|
||||
data_size : Integral
|
||||
data_size : int
|
||||
The total number of bins in the tally corresponding to this filter
|
||||
stride : int
|
||||
Stride in memory for the filter
|
||||
|
||||
Keyword arguments
|
||||
-----------------
|
||||
|
|
@ -1375,11 +1265,6 @@ class DistribcellFilter(Filter):
|
|||
of bins in the corresponding tally, with the filter bin
|
||||
appropriately tiled to map to the corresponding tally bins.
|
||||
|
||||
Raises
|
||||
------
|
||||
ImportError
|
||||
When Pandas is not installed
|
||||
|
||||
See also
|
||||
--------
|
||||
Tally.get_pandas_dataframe(), CrossFilter.get_pandas_dataframe()
|
||||
|
|
@ -1462,7 +1347,7 @@ class DistribcellFilter(Filter):
|
|||
|
||||
# Tile the Multi-index columns
|
||||
for level_key, level_bins in level_dict.items():
|
||||
level_bins = np.repeat(level_bins, self.stride)
|
||||
level_bins = np.repeat(level_bins, stride)
|
||||
tile_factor = data_size // len(level_bins)
|
||||
level_bins = np.tile(level_bins, tile_factor)
|
||||
level_dict[level_key] = level_bins
|
||||
|
|
@ -1478,7 +1363,7 @@ class DistribcellFilter(Filter):
|
|||
# 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)
|
||||
filter_bins = np.repeat(filter_bins, stride)
|
||||
tile_factor = data_size // len(filter_bins)
|
||||
filter_bins = np.tile(filter_bins, tile_factor)
|
||||
df = pd.DataFrame({self.short_name.lower() : filter_bins})
|
||||
|
|
@ -1518,9 +1403,6 @@ class MuFilter(RealFilter):
|
|||
Unique identifier for the filter
|
||||
num_bins : Integral
|
||||
The number of filter bins
|
||||
stride : Integral
|
||||
The number of filter, nuclide and score bins within each of this
|
||||
filter's bins.
|
||||
|
||||
"""
|
||||
|
||||
|
|
@ -1548,7 +1430,7 @@ class MuFilter(RealFilter):
|
|||
'increasing'.format(bins, type(self))
|
||||
raise ValueError(msg)
|
||||
|
||||
def get_pandas_dataframe(self, data_size, **kwargs):
|
||||
def get_pandas_dataframe(self, data_size, stride, **kwargs):
|
||||
"""Builds a Pandas DataFrame for the Filter's bins.
|
||||
|
||||
This method constructs a Pandas DataFrame object for the filter with
|
||||
|
|
@ -1557,8 +1439,10 @@ class MuFilter(RealFilter):
|
|||
|
||||
Parameters
|
||||
----------
|
||||
data_size : Integral
|
||||
data_size : int
|
||||
The total number of bins in the tally corresponding to this filter
|
||||
stride : int
|
||||
Stride in memory for the filter
|
||||
|
||||
Returns
|
||||
-------
|
||||
|
|
@ -1569,11 +1453,6 @@ class MuFilter(RealFilter):
|
|||
corresponding tally, with the filter bin appropriately tiled to map
|
||||
to the corresponding tally bins.
|
||||
|
||||
Raises
|
||||
------
|
||||
ImportError
|
||||
When Pandas is not installed
|
||||
|
||||
See also
|
||||
--------
|
||||
Tally.get_pandas_dataframe(), CrossFilter.get_pandas_dataframe()
|
||||
|
|
@ -1584,8 +1463,8 @@ class MuFilter(RealFilter):
|
|||
|
||||
# Extract the lower and upper energy bounds, then repeat and tile
|
||||
# them as necessary to account for other filters.
|
||||
lo_bins = np.repeat(self.bins[:-1], self.stride)
|
||||
hi_bins = np.repeat(self.bins[1:], self.stride)
|
||||
lo_bins = np.repeat(self.bins[:-1], stride)
|
||||
hi_bins = np.repeat(self.bins[1:], stride)
|
||||
tile_factor = data_size // len(lo_bins)
|
||||
lo_bins = np.tile(lo_bins, tile_factor)
|
||||
hi_bins = np.tile(hi_bins, tile_factor)
|
||||
|
|
@ -1623,9 +1502,6 @@ class PolarFilter(RealFilter):
|
|||
Unique identifier for the filter
|
||||
num_bins : Integral
|
||||
The number of filter bins
|
||||
stride : Integral
|
||||
The number of filter, nuclide and score bins within each of this
|
||||
filter's bins.
|
||||
|
||||
"""
|
||||
|
||||
|
|
@ -1653,7 +1529,7 @@ class PolarFilter(RealFilter):
|
|||
'increasing'.format(bins, type(self))
|
||||
raise ValueError(msg)
|
||||
|
||||
def get_pandas_dataframe(self, data_size, **kwargs):
|
||||
def get_pandas_dataframe(self, data_size, stride, **kwargs):
|
||||
"""Builds a Pandas DataFrame for the Filter's bins.
|
||||
|
||||
This method constructs a Pandas DataFrame object for the filter with
|
||||
|
|
@ -1662,8 +1538,10 @@ class PolarFilter(RealFilter):
|
|||
|
||||
Parameters
|
||||
----------
|
||||
data_size : Integral
|
||||
data_size : int
|
||||
The total number of bins in the tally corresponding to this filter
|
||||
stride : int
|
||||
Stride in memory for the filter
|
||||
|
||||
Returns
|
||||
-------
|
||||
|
|
@ -1674,11 +1552,6 @@ class PolarFilter(RealFilter):
|
|||
corresponding tally, with the filter bin appropriately tiled to map
|
||||
to the corresponding tally bins.
|
||||
|
||||
Raises
|
||||
------
|
||||
ImportError
|
||||
When Pandas is not installed
|
||||
|
||||
See also
|
||||
--------
|
||||
Tally.get_pandas_dataframe(), CrossFilter.get_pandas_dataframe()
|
||||
|
|
@ -1689,8 +1562,8 @@ class PolarFilter(RealFilter):
|
|||
|
||||
# Extract the lower and upper angle bounds, then repeat and tile
|
||||
# them as necessary to account for other filters.
|
||||
lo_bins = np.repeat(self.bins[:-1], self.stride)
|
||||
hi_bins = np.repeat(self.bins[1:], self.stride)
|
||||
lo_bins = np.repeat(self.bins[:-1], stride)
|
||||
hi_bins = np.repeat(self.bins[1:], stride)
|
||||
tile_factor = data_size // len(lo_bins)
|
||||
lo_bins = np.tile(lo_bins, tile_factor)
|
||||
hi_bins = np.tile(hi_bins, tile_factor)
|
||||
|
|
@ -1728,9 +1601,6 @@ class AzimuthalFilter(RealFilter):
|
|||
Unique identifier for the filter
|
||||
num_bins : Integral
|
||||
The number of filter bins
|
||||
stride : Integral
|
||||
The number of filter, nuclide and score bins within each of this
|
||||
filter's bins.
|
||||
|
||||
"""
|
||||
|
||||
|
|
@ -1758,7 +1628,7 @@ class AzimuthalFilter(RealFilter):
|
|||
'increasing'.format(bins, type(self))
|
||||
raise ValueError(msg)
|
||||
|
||||
def get_pandas_dataframe(self, data_size, paths=True):
|
||||
def get_pandas_dataframe(self, data_size, stride, paths=True):
|
||||
"""Builds a Pandas DataFrame for the Filter's bins.
|
||||
|
||||
This method constructs a Pandas DataFrame object for the filter with
|
||||
|
|
@ -1767,8 +1637,10 @@ class AzimuthalFilter(RealFilter):
|
|||
|
||||
Parameters
|
||||
----------
|
||||
data_size : Integral
|
||||
data_size : int
|
||||
The total number of bins in the tally corresponding to this filter
|
||||
stride : int
|
||||
Stride in memory for the filter
|
||||
|
||||
Returns
|
||||
-------
|
||||
|
|
@ -1779,11 +1651,6 @@ class AzimuthalFilter(RealFilter):
|
|||
corresponding tally, with the filter bin appropriately tiled to map
|
||||
to the corresponding tally bins.
|
||||
|
||||
Raises
|
||||
------
|
||||
ImportError
|
||||
When Pandas is not installed
|
||||
|
||||
See also
|
||||
--------
|
||||
Tally.get_pandas_dataframe(), CrossFilter.get_pandas_dataframe()
|
||||
|
|
@ -1794,8 +1661,8 @@ class AzimuthalFilter(RealFilter):
|
|||
|
||||
# Extract the lower and upper angle bounds, then repeat and tile
|
||||
# them as necessary to account for other filters.
|
||||
lo_bins = np.repeat(self.bins[:-1], self.stride)
|
||||
hi_bins = np.repeat(self.bins[1:], self.stride)
|
||||
lo_bins = np.repeat(self.bins[:-1], stride)
|
||||
hi_bins = np.repeat(self.bins[1:], stride)
|
||||
tile_factor = data_size // len(lo_bins)
|
||||
lo_bins = np.tile(lo_bins, tile_factor)
|
||||
hi_bins = np.tile(hi_bins, tile_factor)
|
||||
|
|
@ -1829,20 +1696,9 @@ class DelayedGroupFilter(Filter):
|
|||
Unique identifier for the filter
|
||||
num_bins : Integral
|
||||
The number of filter bins
|
||||
stride : Integral
|
||||
The number of filter, nuclide and score bins within each of this
|
||||
filter's bins.
|
||||
|
||||
"""
|
||||
@property
|
||||
def bins(self):
|
||||
return self._bins
|
||||
|
||||
@property
|
||||
def num_bins(self):
|
||||
return len(self.bins)
|
||||
|
||||
@bins.setter
|
||||
@Filter.bins.setter
|
||||
def bins(self, bins):
|
||||
# Format the bins as a 1D numpy array.
|
||||
bins = np.atleast_1d(bins)
|
||||
|
|
@ -1854,9 +1710,6 @@ class DelayedGroupFilter(Filter):
|
|||
|
||||
self._bins = bins
|
||||
|
||||
@num_bins.setter
|
||||
def num_bins(self, num_bins): pass
|
||||
|
||||
|
||||
class EnergyFunctionFilter(Filter):
|
||||
"""Multiplies tally scores by an arbitrary function of incident energy.
|
||||
|
|
@ -1884,9 +1737,6 @@ class EnergyFunctionFilter(Filter):
|
|||
Unique identifier for the filter
|
||||
num_bins : Integral
|
||||
The number of filter bins (always 1 for this filter)
|
||||
stride : Integral
|
||||
The number of filter, nuclide and score bins within each of this
|
||||
filter's bins.
|
||||
|
||||
"""
|
||||
|
||||
|
|
@ -1894,7 +1744,6 @@ class EnergyFunctionFilter(Filter):
|
|||
self.energy = energy
|
||||
self.y = y
|
||||
self.id = filter_id
|
||||
self._stride = None
|
||||
|
||||
def __eq__(self, other):
|
||||
if type(self) is not type(other):
|
||||
|
|
@ -1954,7 +1803,7 @@ class EnergyFunctionFilter(Filter):
|
|||
y = group['y'].value
|
||||
filter_id = int(group.name.split('/')[-1].lstrip('filter '))
|
||||
|
||||
return cls(energy, y, filter_id)
|
||||
return cls(energy, y, filter_id=filter_id)
|
||||
|
||||
@classmethod
|
||||
def from_tabulated1d(cls, tab1d):
|
||||
|
|
@ -1991,7 +1840,7 @@ class EnergyFunctionFilter(Filter):
|
|||
|
||||
@property
|
||||
def bins(self):
|
||||
raise RuntimeError('EnergyFunctionFilters have no bins.')
|
||||
raise AttributeError('EnergyFunctionFilters have no bins.')
|
||||
|
||||
@property
|
||||
def num_bins(self):
|
||||
|
|
@ -2050,7 +1899,7 @@ class EnergyFunctionFilter(Filter):
|
|||
"""This function is invalid for EnergyFunctionFilters."""
|
||||
raise RuntimeError('EnergyFunctionFilters have no get_bin() method')
|
||||
|
||||
def get_pandas_dataframe(self, data_size, **kwargs):
|
||||
def get_pandas_dataframe(self, data_size, stride, **kwargs):
|
||||
"""Builds a Pandas DataFrame for the Filter's bins.
|
||||
|
||||
This method constructs a Pandas DataFrame object for the filter with
|
||||
|
|
@ -2059,8 +1908,10 @@ class EnergyFunctionFilter(Filter):
|
|||
|
||||
Parameters
|
||||
----------
|
||||
data_size : Integral
|
||||
data_size : int
|
||||
The total number of bins in the tally corresponding to this filter
|
||||
stride : int
|
||||
Stride in memory for the filter
|
||||
|
||||
Returns
|
||||
-------
|
||||
|
|
@ -2071,11 +1922,6 @@ class EnergyFunctionFilter(Filter):
|
|||
EnergyFunctionFilters. The number of rows in the DataFrame is the
|
||||
same as the total number of bins in the corresponding tally.
|
||||
|
||||
Raises
|
||||
------
|
||||
ImportError
|
||||
When Pandas is not installed
|
||||
|
||||
See also
|
||||
--------
|
||||
Tally.get_pandas_dataframe(), CrossFilter.get_pandas_dataframe()
|
||||
|
|
@ -2096,7 +1942,7 @@ class EnergyFunctionFilter(Filter):
|
|||
# hex characters) of the digest are probably sufficient.
|
||||
out = out[:14]
|
||||
|
||||
filter_bins = np.repeat(out, self.stride)
|
||||
filter_bins = np.repeat(out, stride)
|
||||
tile_factor = data_size // len(filter_bins)
|
||||
filter_bins = np.tile(filter_bins, tile_factor)
|
||||
df = pd.concat([df, pd.DataFrame(
|
||||
|
|
|
|||
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